Tutorial: Verwenden von Aufgaben aus der Parallel Programming Library
Nach oben zu Tutorials zur Parallel Programming Library
Inhaltsverzeichnis
In diesem Tutorial wird die Implementierung von Aufgaben aus der Parallel Programming Library (PPL) gezeigt. Aufgaben sind Arbeitseinheiten, die sich in einer Warteschlange befinden und gestartet werden, wenn CPU-Zeit verfügbar ist. Aufgaben können Operationen parallel ausführen. Ein Master-Thread verwaltet diese Warteschlange und weist Threads aus dem Thread-Pool zur Ausführung der Aufgaben zu. Die Anzahl der Threads dieses Thread-Pools ist von der Anzahl der verfügbaren CPUs abhängig.
Erstellen des Projekts
Erstellen Sie ein neues Projekt:
- Für Delphi wählen Sie Datei > Neu > Geräteübergreifende Anwendung - Delphi > Leere Anwendung.
- Für C++Builder wählen Sie Datei > Neu > Geräteübergreifende Anwendung - C++Builder > Leere Anwendung.
Hinzufügen der Komponenten
- Fügen Sie dem Formular eine TButton- und eine TLabel-Komponente hinzu. Mit TButton wird eine Aufgabe gestartet und in TLabel werden die Ergebnisse angezeigt.
- Ziehen Sie eine TScrollBar-Komponente auf das Formular.
- Setzen Sie im Objektinspektor die Eigenschaft Align der Bildlaufleiste auf
Top
.
- Setzen Sie im Objektinspektor die Eigenschaft Align der Bildlaufleiste auf
- Legen Sie eine TFloatAnimation-Komponente auf dem Formular ab.
- Legen Sie die Komponente TFloatAnimation als der Bildlaufleiste untergeordnet fest Die Struktur der Komponenten sollte folgendermaßen aussehen:
- Setzen Sie die Eigenschaft AutoReverse auf
True
. - Setzen Sie die Eigenschaft Duration auf
1
Sekunde. - Setzen Sie die Eigenschaft Enabled auf
True
. - Setzen Sie die Eigenschaft Loop auf
True
. - Setzen Sie die Eigenschaft PropertyName auf
Value
. - Setzen Sie die Eigenschaft StartValue auf
0
und die Eigenschaft StopValue auf100
.
Implementieren der Ereignisbehandlungsroutinen für die Komponenten
Implementieren Sie zuerst die Ereignisbehandlungsroutine für das Ereignis OnClick von TButton. Schreiben Sie dazu Code wie den folgenden:
procedure TForm1.Button1Click(Sender: TObject);
var
lValue: Integer;
begin
Label1.Text := '--';
{Some calculation that takes time}
Sleep(3000);
lValue := Random(10);
Label1.Text := lValue.ToString;
end;
end.
void __fastcall TForm1::Button1Click(TObject *Sender)
{
int lValue;
Label1->Text = "--";
//{Some calculation that takes time}
Sleep(3000);
lValue = Random(10);
Label1->Text = String(lValue);
}
Dieser Code ist ein Beispiel für eine lange Berechnung, die beginnt, wenn Sie auf die Schaltfläche drücken. Es wird 3 Sekunden gewartet und dann eine Zahl zwischen 0 und 10 angezeigt.
Ausführen der Anwendung ohne PPL-Implementierung
Nun können Sie die Anwendung ausführen:
- Drücken Sie
F9
, oder wählen Sie Start > Start.
Die Bildlaufleiste bewegt sich von rechts nach links. Sobald Sie jedoch auf die Schaltfläche drücken und die lange Berechnung beginnt, wird die Bildlaufleiste angehalten, bis die Berechnung beendet ist. Offensichtlich ist dies nicht das erwartete Verhalten. Im nächsten Abschnitt wird gezeigt, wie Sie dieses Verhalten mit der TTask-Funktionalität der PPL verbessern können.
Implementieren der TTask-Funktionalität
In diesem Abschnitt wird gezeigt, wie Sie die lange Berechnung (die als OnClick-Ereignis implementiert ist) in eine TTask einbetten, damit dieser Prozess parallel ausgeführt werden kann.
Benennen Sie zunächst im Anwendungsformular die Komponenten TButton und TLabel in ButtonTask1 bzw. LabelTask1 um.
Beziehen Sie anschließend die PPL-Bibliothek in das Projekt ein:
uses
System.Threading;
#include <System.Threading.hpp>
Für die Ausführung der Berechnung als Aufgabe stellt die PPL die Methode TTask.Run bereit. Ändern Sie den Code folgendermaßen:
procedure TForm1.ButtonTask1Click(Sender: TObject);
var
lValue: Integer;
begin
Label1.Text := '--';
TTask.Run(procedure
begin
{Some calculation that takes time}
Sleep(3000);
lValue := Random(10);
TThread.Synchronize(nil,
procedure
begin
Label1.Text := lValue.ToString;
end);
end);
end;
Im obigen Code wird aus den möglichen Eingabeparameteroptionen, die die Methode TTask.Run in Delphi bereitstellt, eine anonyme Methode für die lange Berechnung verwendet.
Beziehen Sie auch den Code für die Klassen TCppSync
und TCppTask
ein:
class TCppSync : public TCppInterfacedObject<TThreadProcedure> {
int &lValue;
TLabel *Label;
public:
TCppSync(int &l, TLabel *lbl):lValue(l),Label(lbl)
{}
void __fastcall Invoke(){
Label->Text = String(lValue);
}
};
class TCppTask : public TCppInterfacedObject<TProc> {
int &lValue;
TLabel *Label;
public:
TCppTask(int &l, TLabel *lbl): lValue(l), Label(lbl)
{}
void __fastcall Invoke(){
Sleep(3000);
lValue = Random(10);
TThread::Synchronize(0,_di_TThreadProcedure(new TCppSync(lValue, Label)));
}
};
void __fastcall TForm1::ButtonTask1Click(TObject *Sender)
{
LabelTask1->Text = "--";
TTask::Run(_di_TProc(new TCppTask(lValue, LabelTask1)));
}
Fügen Sie die Deklaration von lValue
in den private-Abschnitt der Header-Datei ein:
private: // User declarations
int lValue;
Im obigen Code wird aus den möglichen Eingabeparameteroptionen, die die Methode TTask.Run in C++ bereitstellt, ein TProc-Typ für die lange Berechnung verwendet.
Ausführen der Anwendung mit der TTask-Funktionalität
Nun können Sie die Anwendung ausführen:
- Drücken Sie
F9
, oder wählen Sie Start > Start.
Wenn Sie jetzt ButtonTask1 drücken, bleibt die Bildlaufleisten-Aktion aktiv und wird nicht unterbrochen. Mit der TTask-Funktionalität der PPL können Sie mehrere Aufgaben parallel ausführen.