2009-06-06 10 views
6

Plusieurs tâches de mon application fonctionnent en arrière-plan. Ils se connectent à la base de données et exécutent des requêtes de sélection chronophages. Dans la plupart des cas, ces requêtes renvoient uniquement plusieurs enregistrements. De temps en temps, cependant, ils peuvent renvoyer des dizaines de milliers de disques. Tout cela est ensuite traité en boucle.Delphi - Réglage du temps de repos du fil

Étant donné qu'une telle situation peut se produire dans plusieurs threads en même temps, je ne souhaite pas que mon application utilise 100% du temps CPU lorsque ces threads traitent des données; Je ne veux pas non plus que tous les threads se battent pour le temps du processeur. Par conséquent, j'appelle la fonction Sleep() dans chaque itération des boucles dans ces threads.

Je ne sais pas, cependant, comment ajuster le temps de sommeil. Je ne veux pas que les boucles durent éternellement, donc la période de sommeil ne peut pas être trop longue. Je l'ai mis à 2 millisecondes dans chaque itération (dans chaque thread) (pourquoi 2ms? - c'est une bonne question :)). D'autre part, je pensais que je pouvais prolonger le temps de sommeil, mais appeler le sommeil seulement une fois toutes les itérations (disons Sommeil (100) toutes les 50 itérations). Quelle approche devrais-je choisir? Une insertion des boucles prend environ 30 ms chacune (sans sommeil).

Veuillez nous aviser.

Merci!
Mariusz.

Répondre

9

L'appel Sleep() n'a aucun sens. Utilisez toute la puissance de traitement que vous pouvez obtenir, et laissez le système déterminer comment programmer au mieux vos threads. L'appel Sleep() ne provoquera que des changements de contexte supplémentaires et réduira votre débit. Si le traitement en arrière-plan interfère avec votre thread principal ou d'autres applications, réduisez la priorité des threads d'arrière-plan en conséquence.

Si vous voulez laisser les threads en veille pour limiter la quantité de données qu'ils génèrent pour les consommateurs, regardez dans les files d'attente producteur-consommateur. Avoir les threads du producteur simplement bloquer lorsque leur file d'attente est pleine, de cette façon, vous n'aurez pas du tout besoin de jouer avec le timing.

Notez également que l'utilisation d'une CPU maximale est généralement une bonne chose, en particulier sur les processeurs modernes. Même sur les ordinateurs portables ayant un temps de charge élevé, il est préférable de prolonger artificiellement le temps dont votre tâche a besoin, car le processeur/l'ensemble du système sera plus rapidement capable d'entrer dans des états de faible puissance.

+0

Mais si cela fonctionne en arrière-plan sur un ordinateur qui a aussi quelqu'un qui travaille sur (par exemple, écrire une feuille de calcul), vous ne voulez que le processus d'arrière-plan rende le processus de premier plan inutilisable. – dummzeuch

+2

Vrai, mais c'est pourquoi j'ai écrit que la priorité des threads d'arrière-plan peut être réduite, en gardant d'autres applications (ou le thread principal) sensibles tout en utilisant le potentiel du système complet. Sur les systèmes modernes (multi-core), le fait que tous les noyaux soient suffisamment chargés est beaucoup plus problématique que le manque de réactivité de l'application de premier plan. Et les E/S massives non optimisées représentent une menace beaucoup plus grande pour la facilité d'utilisation d'un système qu'une charge CPU élevée, de toute façon. – mghie

2

Il peut être préférable d'utiliser le mode veille pour contrôler vos threads. Étant donné que votre appel de base de données peut renvoyer 1-1000 entrées d'enregistrements pour le traitement, il peut être judicieux de séparer votre application en deux couches, en utilisant éventuellement une file d'attente de messages pour mettre les requêtes en tampon. Votre application peut appeler un service de données, puis le service de données exécute la requête et envoie des messages de données individuels (ou des blocs de messages, etc.) vers une file d'attente. Votre application peut ensuite créer autant de threads que nécessaire pour traiter les messages. Plus de threads signifie un traitement plus rapide au détriment du CPU, mais vous pouvez ajuster cela pour obtenir le bon équilibre.

3

Vous feriez mieux de créer des threads de faible priorité et de les laisser fonctionner sans sommeil, sinon vous n'utilisez pas toute la puissance du processeur. Par exemple sur les systèmes multi-cœurs/multi-cpu. Ou si votre système est inactif à 100%: pourquoi attendre ou dormir?

Cependant, si vous avez besoin de dormir, notez que sleep (1) attend 10-15ms (!) À cause du timelice Windows par défaut. Vous pouvez utiliser timeBeginPeriod (1) de l'unité MMSystem.pas pour définir la résolution à 1ms :-) (j'ai utilisé ceci pour la communication série).

0

utilisez TThread.Sleep() de System.Classes au lieu de Sleep() de WinApi.Windows

// Winapi.Windows contains GetTickCount and Sleep 
// System.Classes contains TThread (universal option) // TThread.GetTickCount() // TThread.Sleep() 
uses System.Types, System.Classes, Vcl.Forms; 

// puis dans votre processus utilisez ce qui suit

TThread.Sleep(0); 

Application.ProcessMessages(); // clear all Vcl messages // part of Vcl.Forms 
CheckSynchronize(); // check all threaded events