Utilisation de TTask de la bibliothèque de programmation parallèle

De RAD Studio
Aller à : navigation, rechercher

Remonter à Utilisation de la bibliothèque de programmation parallèle


La bibliothèque de programmation parallèle fournit une classe TTask pour exécuter une ou plusieurs tâches en parallèle. Une tâche est une unité de travail à effectuer. La PPL fait l'association entre la tâche et le thread qui effectue la tâche, de sorte que vous pouvez exécuter plusieurs tâches en parallèle sans avoir à créer vos propres threads personnalisés ni à les gérer.

TTask crée et gère l'interaction avec des instances de ITask. ITask est une interface qui fournit un ensemble de méthodes et de propriétés pour démarrer, attendre, annuler et aussi une propriété pour l'état (Created, WaitingToRun, Running, Completed, WaitingForChildren, Canceled, Exception).

Exécution d'une tâche en arrière-plan

Une fonctionnalité de TTask consiste à empêcher le verrouillage de l'interface utilisateur lorsque vous voulez démarrer quelque chose en arrière-plan. L'exemple de code suivant montre comme exécuter une seule tâche et la démarrer :

Delphi :

 
procedure TForm1.Button1Click(Sender: TObject);
var
 aTask: ITask;
begin
 aTask := TTask.Create(
   procedure
   begin
     sleep (3000); // 3 seconds
     TThread.Synchronize(TThread.Current,
       procedure
       begin
         ShowMessage ('Hello');
       end);
   end);
   aTask.Start;
end;

C++ :

Si vous utilisez un compilateur C++ amélioré par Clang, vous pouvez utiliser les expressions lambda :

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    _di_ITask task = TTask::Create([&](){
        Sleep(3000);
        ShowMessage("Hello");
    });
    task->Start();
}

Pour les compilateurs C++, vous pouvez déclarer une sous-classe TProc et en utiliser une instance transtypée en _di_TProc :

class TCppTask : public TCppInterfacedObject<TProc> {
public:
    void __fastcall Invoke() {
        Sleep(3000);
        ShowMessage("Hello");
    }
};

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    _di_ITask task = TTask::Create(_di_TProc(new TCppTask()));
    task->Start();
}

Attente de la terminaison des tâches

TTask fournit WaitForAll et WaitForAny pour attendre la fin de toutes les tâches ou d'une tâche. WaitForAll renvoie le résultat lorsque toutes les tâches sont terminées, tandis que WaitForAny vous indique que la première tâche est terminée. Par exemple, si vous avez deux tâches A et B qui durent respectivement 3 et 5 secondes, le temps d'attente avant d'obtenir un résultat est :

L'exemple suivant utilise la méthode WaitForAll method:

Delphi :

 
procedure TForm1.MyButtonClick(Sender: TObject);
var 
  tasks: array of ITask; 
  value: Integer; 
begin 
  Setlength (tasks ,2); 
  value := 0; 

 tasks[0] := TTask.Create (procedure () 
  begin 
   sleep(3000);
   TInterlocked.Add (value, 3000); 
  end); 
 tasks[0].Start; 

 tasks[1] := TTask.Create (procedure () 
   begin 
   sleep (5000);
   TInterlocked.Add (value, 5000);
 end); 
 tasks[1].Start; 
 
 TTask.WaitForAll(tasks); 
 ShowMessage ('All done: ' + value.ToString); 
end;

C++ :

Si vous utilisez un compilateur C++ amélioré par Clang, vous pouvez utiliser les expressions lambda :

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    _di_ITask tasks[2];
    int value = 0;

    tasks[0] = TTask::Create([&](){
        Sleep(3000);
        TInterlocked::Add(value, 3000);
    });
    tasks[0]->Start();

    tasks[1] = TTask::Create([&](){
        Sleep(5000);
        TInterlocked::Add(value, 5000);
    });
    tasks[1]->Start();

    TTask::WaitForAll(tasks, sizeof(tasks)/sizeof(tasks[0])-1);
    ShowMessage("All done! " + IntToStr(value));
}

Pour les compilateurs C++, vous pouvez déclarer une sous-classe TProc et en utiliser une instance transtypée en _di_TProc :

class TCppTask : public TCppInterfacedObject<TProc> {
public:
    TCppTask(int &value, int increase) : m_value(value), m_increase(increase) {}
    void __fastcall Invoke() {
        Sleep(m_increase);
        TInterlocked::Add(m_value, m_increase);
    }
protected:
    int& m_value;
    int m_increase;
};

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    _di_ITask tasks[2];
    int value = 0;

    tasks[0] = TTask::Create(_di_TProc(new TCppTask(value, 3000)));
    tasks[0]->Start();

    tasks[1] = TTask::Create(_di_TProc(new TCppTask(value, 5000)));
    tasks[1]->Start();

    TTask::WaitForAll(tasks,(sizeof(tasks)/sizeof(tasks[0])-1));
    ShowMessage("All done! " + IntToStr(value));
}

Voir aussi