Je crée une application de console qui doit exécuter plusieurs threads afin d'accomplir une tâche. Mon problème est que les threads sont en cours d'exécution l'un après l'autre (Thread1 Démarrer -> Travail -> Fin et seulement Démarrer le thread2) au lieu de courir tout en même temps. De plus, je ne veux pas que plus de 10 threads travaillent dans le même temps (problèmes de performance). BOWER est un exemple de code d'application de la console et du DataModule utilisé. Ma candidature fonctionne de la même manière. J'ai utilisé un DataModule car une fois les threads terminés, je dois remplir une base de données avec ces informations. Il existe également des commentaires dans le code d'explication qui est la raison de faire quelque chose.
Code de la console de l'application: p> et code de données p> donc, comme je l'ai dit le problème que mes fils fonctionnent l'un après l'autre, au lieu de travailler tout en même temps. Aussi, j'ai vu que, parfois, le premier fil a fonctionné, après que tout le reste ne soit que créé et fini. Dans mon application, tout le code est protégé par TRY-SAUFS, mais aucune erreur n'est soulevée. p> Quelqu'un peut-il me donner un conseil? P> P>
3 Réponses :
à tout le moins que vous devriez mettre à l'extérieur de la boucle principale. Cette boucle d'attente est ce qui cause la maintien. Pour chaque entier I du Mainloop, il attend que la FtheadCount tombe à zéro. P> sur un Sidenote: Normalement, vous n'avez pas besoin de protéger les variables locales avec des sections critiques. Bien que les messages de traitement dedans, il puisse subir des objets, car il peut provoquer une réintensif. P> P>
J'ai une unité qui fait exactement ce dont vous avez besoin. Il suffit de le télécharger à partir de: p>
à l'intérieur, vous avez deux classes: p>
Le TtaSkQueue peut être utilisé autonome avec des filets de Vanila simples par exemple. Il bloque à l'intérieur d'un seul fil et files d'attente les demandes. P>
Si cela ne suffit pas, vous pouvez vérifier l'omnithreadlibrary à: p>
Ceci est une puissant bibliothèque de filetage, de loin supérieure à ce que j'ai. Mais aussi plus compliqué à utiliser (mais toujours très facile par rapport au filetage classique). P>
Je ne pense pas qu'il veuille que les fils s'enoncent l'un après l'autre. Il n'est pas sûr de savoir pourquoi ils ne fonctionnent pas en parallèle.
J'ai suivi la suggestion de Marjan et le code suivant semble fonctionner correctement. Je réponds à ma propre question afin de fournir un code de réponse, qui peut être analysé par d'autres personnes et corrigé si nécessaire.
unit Unit1; interface uses SysUtils, Classes, SyncObjs, Windows, Forms, Dialogs; var FCritical: TRTLCriticalSection; type TTestThread = class(TThread) protected procedure Execute;override; end; TDataModule1 = class(TDataModule) procedure DataModuleCreate(Sender: TObject); procedure DataModuleDestroy(Sender: TObject); private { Déclarations privées } public procedure execute; procedure CreateThread(); procedure Onterminatethrd(Sender: TObject); end; var DataModule1 : TDataModule1; FthreadCount : Integer; implementation {$R *.dfm} { TTestThread } procedure TTestThread.Execute; var f : TextFile; i : integer; begin AssignFile(f, 'd:\a\a' + inttostr(FthreadCount) + '.txt'); if fileexists('d:\a\a' + inttostr(FthreadCount) + '.txt') then Append(f) else Rewrite(f); try i := 0; while i <= 1000000 do Inc(i); Writeln(f, 'done '+floattostr(self.Handle)); finally CloseFile(f); end; end; { TDataModule1 } procedure TDataModule1.CreateThread; var aThrd : TTestThread; begin aThrd := TTestThread.Create(True); aThrd.FreeOnTerminate := True; EnterCriticalSection(fcritical); Inc(FthreadCount); LeaveCriticalSection(fcritical); aThrd.OnTerminate:=Onterminatethrd; try aThrd.Resume; except FreeAndNil(aThrd); end; end; procedure TDataModule1.Onterminatethrd(Sender: TObject); begin EnterCriticalSection(fcritical); Dec(FthreadCount); LeaveCriticalSection(fcritical); end; procedure TDataModule1.DataModuleCreate(Sender: TObject); begin InitializeCriticalSection(fcritical); end; procedure TDataModule1.DataModuleDestroy(Sender: TObject); begin DeleteCriticalSection(fcritical); end; procedure TDataModule1.execute; var i : integer; begin i := 0; try while i < 1000 do begin while (FthreadCount = 10) do begin Application.ProcessMessages; CheckSynchronize end; CreateThread; Inc(i); end; while FthreadCount > 0 do begin Application.ProcessMessages; CheckSynchronize; end; except on e:Exception do // end; end; end.
Il existe un article et un exemple sur la mise en œuvre de sémaphores avec Delphi ici: edn.embarcadero.com/article/29908 a>
Un bon moyen de s'assurer que plus de 10 threads courent immédiatement pour utiliser un Semaphore i>. Acquérez-le avant de créer un thread et que chaque fil est libéré lors de la résiliation. S'il y a déjà 10 threads en cours d'exécution, la onzième tentative d'acquisition du sémaphore bloquera jusqu'à ce qu'un autre fil se termine. Ensuite, vous n'avez pas besoin de ces processus de processage. Ces boucles ne font que manger du temps de processeur parce que votre application n'a jamais envoie i> tous les messages, il n'y aura jamais rien à traiter.
Une autre étape que vous pouvez prendre est de n'appeler que
checksynchroniser code> quand il y a en fait quelque chose à synchroniser avec. Avec votre sémaphore configuré, appelez MSGWAITECOMULTIPLEObjects sur la poignée SEMAPHORE et la variable globale
Synceventer code>. Lisez à ce sujet dans les classes.pas. Si le sémaphore est signalé, créez un nouveau fil. Si l'événement est signalé, appelez CheckSynchroniser.
Rob, merci beaucoup pour les informations. J'ai lu maintenant sur les sémaphores, mais je ne suis pas sûr de bien comprendre comment dois-je le mettre en œuvre. D'après ce que j'ai lu, j'ai besoin d'utiliser WaitforSingleObject (poignée, infinie) - pour le fil de finition pour terminer tout le cycle, mais comment puis-je savoir quand commencer un autre fil? J'ai vu des exemples alors je crois que je dois créer un sémaphore avec 10 threads, mais lorsque je crée comment je crée un nouveau fil et le déjeuner dans Semaphore? Quelqu'un peut-il me fournir un petit exemple basé sur mon exemple? Merci d'avance!