Verwenden von TTask aus der Parallel Programming Library

Aus RAD Studio
Wechseln zu: Navigation, Suche

Nach oben zu Verwenden der Parallel Programming Library


Die Parallel Programming Library (PPL) stellt die Klasse TTask bereit, mit der eine Aufgabe oder mehrere Aufgaben parallel ausgeführt werden können. Eine Aufgabe (Task) ist eine Arbeitseinheit, die erledigt werden muss. Die PPL übernimmt die Zuordnung zwischen der Aufgabe und dem Thread, der die Aufgabe durchführt, damit Sie mehrere Aufgaben parallel ausführen können, ohne eigene benutzerdefinierte Threads erstellen und verwalten zu müssen.

TTask erstellt und verwaltet die Interaktion mit Instanzen von ITask. ITask ist ein Interface, das eine Reihe von Methoden und Eigenschaften für den Start, das Warten (Wait) und den Abbruch (Cancel) sowie eine Eigenschaft für den Status (Created, WaitingToRun, Running, Completed, WaitingForChildren, Canceled, Exception) bereitstellt.

Ausführen einer Aufgabe im Hintergrund

Eine Funktionalität von TTask ist, die das Blockieren der Benutzerschnittstelle zu verhindern, wenn Sie etwas im Hintergrundprevent starten möchten. Das folgende Codebeispiel zeigt, wie eine einzelne Aufgabe ausgeführt und gestartet wird:

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++:

Wenn Sie einen durch Clang basierten C++-Compiler verwenden, können Sie Lambda-Ausdrücke verwenden:

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

Sie können für jeden C++-Compiler eine TProc-Unterklasse deklarieren, und ihre Instanz, die als _di_TProc umgewandelt wird, verwenden:

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();
}

Auf die Ausführung von Aufgaben warten

Mit WaitForAll und WaitForAny von TTask kann auf den Abschluss aller oder einer beliebigen Aufgabe gewartet werden. WaitForAll informiert Sie über den Abschluss aller Aufgaben und WaitForAny über die erste Aufgabe, die abgeschlossen wurde. Zum Beispiel: Wenn zwei Aufgaben, A und B, 3 bzw. 5 Sekunden benötigen, erhalten Sie das Ergebnis in der folgenden Zeit:

Das folgende Beispiel verwendet die WaitForAll-Methode:

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++:

Wenn Sie einen durch Clang basierten C++-Compiler verwenden, können Sie Lambda-Ausdrücke verwenden:

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));
}

Sie können für jeden C++-Compiler eine TProc-Unterklasse deklarieren, und ihre Instanz, die als _di_TProc umgewandelt wird, verwenden:

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));
}

Siehe auch