Planificateur de tâches en C++ : création et gestion des tâches

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Planificateur de tâches en C++ : guide complet



Le planificateur de tâches (Task Scheduler) est un outil puissant permettant d'automatiser l'exécution de code à des moments précis ou à intervalles réguliers. En C++, l'implémentation d'un tel planificateur nécessite une compréhension du multithreading, de la synchronisation et de la gestion des intervalles de temps. Dans cet article, nous allons voir comment créer votre propre planificateur de tâches à partir de zéro, en utilisant la bibliothèque standard C++ (C++11 et versions ultérieures).



Composants principaux du planificateur

Tout planificateur de tâches se compose de plusieurs éléments clés :

  • Stockage des tâches — une file d'attente ou un conteneur pour stocker les tâches planifiées.
  • Minuteur — un mécanisme qui détermine quand une tâche doit être exécutée.
  • Pool de threads — pour l'exécution parallèle des tâches sans bloquer le thread principal.
  • Mécanisme d'annulation — la possibilité d'annuler une tâche avant son exécution.


Implémentation simple d'un planificateur avec un seul thread

Commençons par un exemple de base où les tâches sont exécutées séquentiellement dans un thread d'arrière-plan :



#include <iostream>#include <thread>#include <chrono>#include <functional>#include <queue>#include <mutex>#include <condition_variable>

class TaskScheduler {public: // Planifie une tâche avec un délai void schedule(std::function<void()> task, int delay_ms) { std::lock_guard<std::mutex> lock(mutex_); tasks_.push({std::chrono::steady_clock::now() + std::chrono::milliseconds(delay_ms), task}); cv_.notify_one(); }

// Démarre le planificateur dans un thread séparé void start() { worker_ = std::thread([this]() { while (!stop_) { std::unique_lock<std::mutex> lock(mutex_); if (tasks_.empty()) { cv_.wait(lock, [this]() { return !tasks_.empty() || stop_; }); } if (stop_) break;

auto now = std::chrono::steady_clock::now(); auto& top = tasks_.top(); if (top.time <= now) { auto task = top.task; tasks_.pop(); lock.unlock(); task(); // Exécute la tâche } else { cv_.wait_until(lock, top.time); } } }); }

void stop() { stop_ = true; cv_.notify_all(); if (worker_.joinable()) worker_.join(); }

private: struct Task { std::chrono::steady_clock::time_point time; std::function<void()> task; bool operator>(const Task& other) const { return time > other.time; } };

std::priority_queue<Task, std::vector<Task>, std::greater<Task>> tasks_; std::mutex mutex_; std::condition_variable cv_; std::thread worker_; bool stop_ = false;};

int main() { TaskScheduler scheduler; scheduler.start();

scheduler.schedule([]() { std::cout << "Tâche 1 exécutée après 2 secondes"; }, 2000);

scheduler.schedule([]() { std::cout << "Tâche 2 exécutée après 1 seconde"; }, 1000);

std::this_thread::sleep_for(std::chrono::seconds(3)); scheduler.stop(); return 0;}


Planificateur avec un pool de threads pour l'exécution parallèle

Pour des scénarios plus complexes, où les tâches peuvent prendre du temps à s'exécuter, il est préférable d'utiliser un pool de threads. Voici un exemple avec un pool minimal :



#include <vector>#include <queue>#include <thread>#include <mutex>#include <condition_variable>#include <f                    

Recommendations