Verwenden von TTask aus der Parallel Programming Library
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:
- Sequenziell (ohne TTask/ITask) = 8 Sekunden
- TTask.WaitForAny = 3 Sekunden
- TTask.WaitForAll = 5 Sekunden
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));
}