Tutoriel : Utilisation des tâches de la bibliothèque de programmation parallèle
Remonter à Tutoriels Bibliothèque de programmation parallèle
Sommaire
Ce tutoriel explique comment implémenter une application en utilisant les tâches de la bibliothèque de programmation parallèle (PPL). Ces tâches sont des unités de travail qui se trouvent dans la file d'attente et qui démarrent lorsque le temps CPU est disponible. Les tâches peuvent exécuter des opérations en parallèle. Un thread maître gère cette file d'attente et alloue des threads à partir du pool de threads pour qu'ils exécutent les tâches. Ce pool de threads comporte un nombre de threads dépendant du nombre de CPU disponibles.
Création du projet
Créez un nouveau projet :
- Pour Delphi, choisissez Fichier > Nouveau > Application multi-périphérique - Delphi > Application vide.
- Pour C++Builder, choisissez Fichier > Nouveau > Application multi-périphérique - C++Builder > Application vide.
Ajout des composants
- Ajoutez un composant TButton et un composant TLabel à la fiche. TButton démarrera une tâche et TLabel affichera les résultats.
- Déposez un composant TScrollBar sur la fiche.
- Définissez la propriété Align de la barre de défilement sur
Top
dans l'inspecteur d'objets.
- Définissez la propriété Align de la barre de défilement sur
- Déposez un TFloatAnimation sur la fiche.
- Imbriquez le TFloatAnimation sous la barre de défilement. La structure des composants doit ressembler à ceci :
- Définissez la propriété AutoReverse sur
True
. - Définissez la propriété Duration sur
1
seconde. - Définissez la propriété Enabled sur
True
. - Définissez la propriété Loop sur
True
. - Définissez la propriété PropertyName sur
Value
. - Définissez la propriété StartValue sur
0
et la propriété StopValue sur100
.
Implémentation des gestionnaires d'événement pour les composants
Commencez par implémenter le gestionnaire d'événement pour l'événement OnClick de TButton. Pour cela, écrivez le code comme suit :
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);
}
Ce code est un exemple d'un long processus de calcul qui démarre lorsque vous appuyez sur le bouton. Il suspend les opérations pendant 3 secondes (veille) puis affiche un numéro aléatoire entre 0 et 10.
Exécution de l'application sans l'implémentation de la PPL
A ce stade, vous pouvez exécuter l'application :
- Appuyez sur
F9
ou choisissez Exécuter > Exécuter.
Vous voyez la barre de défilement se déplacer de gauche à droite. Mais dès que vous appuyez sur le bouton et que le long calcul démarre, la barre de défilement s'arrête jusqu'à ce que le calcul soit terminé. Ce n'est évidemment pas le comportement attendu. C'est pourquoi la section suivante explique comment améliorer ce comportement en utilisant la fonctionnalité TTask de la PPL.
Implémentation de la fonctionnalité TTask
Cette section explique comment intégrer le long calcul (implémenté en tant qu'événement OnClick) dans une classe TTask pour que ce processus puisse s'exécuter en parallèle.
D'abord, à l'aide de la fiche précédente de l'application, renommez les composants TButton et TLabel en tant que ButtonTask1 et LabelTask1 respectivement.
Puis, incluez la bibliothèque PPL dans le projet :
uses
System.Threading;
#include <System.Threading.hpp>
Pour exécuter le processus de calcul en tant que tâche, la PPL fournit la méthode TTask.Run. Pour ce faire, modifiez et écrivez le code comme suit :
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;
Le code ci-dessus utilise une méthode anonyme pour effectuer le long calcul, mais il existe différentes options de paramètres d'entrée possibles avec la méthode TTask.Run dans Delphi.
Incluez également le code pour les classes TCppSync
et TCppTask
:
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)));
}
Ajoutez la déclaration de lValue
dans la section private du fichier d'en-tête :
private: // User declarations
int lValue;
Le code ci-dessus utilise un type TProc pour effectuer le long calcul, mais il existe différentes options de paramètres possibles avec la méthode TTask.Run dans C++.
Exécution de l'implémentation de la fonctionnalité TTask
A ce stade, vous pouvez exécuter l'application :
- Appuyez sur
F9
ou choisissez Exécuter > Exécuter.
Dans ce cas, lorsque vous appuyez sur le bouton ButtonTask1, vous pouvez voir que l'action scrollBar reste active et n'est pas interrompue. Donc, en utilisant la fonctionnalité TTask de la PPL, vous pouvez exécuter plusieurs tâches en parallèle.