Threads de service
Remonter à Applications service
Chaque service dispose de son propre thread (Vcl.SvcMgr.TServiceThread), donc si votre application service implémente plusieurs services, vous devez vous assurer que l'implémentation de vos services est compatible avec l'utilisation de threads. La classe TServiceThread est ainsi conçue de façon à implémenter le service dans le gestionnaire d'événement OnExecutede TService. Le thread du service dispose de sa propre méthode Execute qui contient une boucle appelant les gestionnaires OnStart et OnExecute du service avant de traiter de nouvelles requêtes.
Comme le traitement des requêtes de service peut prendre longtemps et que l'application service peut recevoir simultanément plusieurs requêtes d'un ou de plusieurs clients, il est plus efficace de lancer un nouveau thread (dérivé de System.Classes.TThread, et non de TServiceThread) pour chaque requête et de déplacer l'implémentation du service dans la méthode Execute du nouveau thread. Cela permet à la boucle Execute du thread du service de traiter continuellement de nouvelles requêtes sans avoir à attendre la fin du gestionnaire OnExecute du service. Cette manière de procéder est illustrée par l'exemple suivant.
Remarque : Ce service sonne tous les 500 millisecondes depuis le thread standard. Il gère la pause, la reprise et l'arrêt du thread quand on indique au service de se suspendre, de reprendre ou de s'arrêter.
Pour créer l'exemple :
- Choisissez Fichier > Nouveau > Autre et double-cliquez sur Application service dans la boîte de dialogue Nouveaux éléments. La fenêtre Service1 apparaît.
- Dans la section interface de votre unité, déclarez un nouveau descendant de TThread nommé TSparkyThread. C'est le thread qui réalise le travail pour le service. Il doit être déclaré comme suit :
TSparkyThread = class(TThread)
public
procedure Execute; override;
end;
class TSparkyThread : public TThread
{
private:
protected:
void __fastcall Execute();
public:
__fastcall TSparkyThread(bool CreateSuspended);
};
- Dans la section implémentation de l'unité, créez une variable globale pour une instance de TsparkyThread :
var
SparkyThread: TSparkyThread;
TSparkyThread *SparkyThread;// Ajoutez ce code en tant que constructeur
__fastcall TSparkyThread::TSparkyThread(bool CreateSuspended)
: TThread(CreateSuspended)
{
}
- Dans la section implémentation de la méthode Execute de TSparkyThread (la fonction thread), ajoutez le code suivant :
procedure TSparkyThread.Execute;
begin
while not Terminated do
begin
Beep;
Sleep(500);
end;
end;
void __fastcall TSparkyThread::Execute()
{
while (!Terminated)
{
Beep();
Sleep(500);
}
}
- Sélectionnez la fenêtre service (Service1) et double-cliquez sur l'événement OnStart dans l'inspecteur d'objets. Ajoutez le gestionnaire d'événement OnStart suivant :
procedure TService1.Service1Start(Sender: TService; var Started: Boolean);
begin
SparkyThread := TSparkyThread.Create(False);
Started := True;
end;
void __fastcall TService1::Service1Start(TService *Sender, bool &Started)
{
SparkyThread = new TSparkyThread(false);
Started = true;
}
- Double-cliquez sur l'événement OnContinue dans l'inspecteur d'objets. Ajoutez le gestionnaire d'événement OnContinue suivant :
procedure TService1.Service1Continue(Sender: TService; var Continued: Boolean);
begin
SparkyThread.Resume;
Continued := True;
end;
void __fastcall TService1::Service1Continue(TService *Sender, bool &Continued)
{
SparkyThread->Resume();
Continued = true;
}
- Double-cliquez sur l'événement OnPause dans l'inspecteur d'objets. Ajoutez le gestionnaire d'événement OnPause suivant :
procedure TService1.Service1Pause(Sender: TService; var Paused: Boolean);
begin
SparkyThread.Suspend;
Paused := True;
end;
void __fastcall TService1::Service1Pause(TService *Sender, bool &Paused)
{
SparkyThread->Suspend();
Paused = true;
}
- Enfin, double-cliquez sur l'événement OnStop dans l'inspecteur d'objets. Ajoutez le gestionnaire d'événements OnStop suivant :
procedure TService1.Service1Stop(Sender: TService; var Stopped: Boolean);
begin
SparkyThread.Terminate;
Stopped := True;
end;
void __fastcall TService1::Service1Stop(TService *Sender, bool &Stopped)
{
SparkyThread->Terminate();
Stopped = true;
}
Dans le cadre du développement d'applications serveur, la décision de lancer un nouveau thread dépend de la nature du service rendu, du nombre prévu de connexions et du nombre prévu de processeurs dont dispose la machine exécutant le service.