Dans mon application C#/NET 3.5 actuelle, j'ai une file d'attente de tâches (thread-safe) et j'ai 5 threads de travail qui doivent constamment chercher des tâches dans la file d'attente. Si une tâche est disponible, n'importe quel travailleur va la déquiler et prendre les mesures requises.Quelle est la méthode la plus efficace pour que les threads de travail attendent les tâches?
Ma classe de thread de travail est la suivante:
public class WorkerThread
{
//ConcurrentQueue is my implementation of thread safe queue
//Essentially just a wrapper around Queue<T> with synchronization locks
readonly ConcurrentQueue<CheckPrimeTask> mQ;
readonly Thread mWorker;
bool mStop;
public WorkerThread (ConcurrentQueue<CheckPrimeTask> aQ) {
mQ = aQ;
mWorker = new Thread (Work) {IsBackground = true};
mStop = false;
}
private void Work() {
while (!mStop) {
if (mQ.Count == 0) {
Thread.Sleep (0);
continue;
}
var task = mQ.Dequeue();
//Someone else might have been lucky in stealing
//the task by the time we dequeued it!!
if (task == null)
continue;
task.IsPrime = IsPrime (task.Number);
task.ExecutedBy = Thread.CurrentThread.ManagedThreadId;
//Ask the threadpool to execute the task callback to
//notify completion
ThreadPool.QueueUserWorkItem (task.CallBack, task);
}
}
private bool IsPrime (int number) {
int limit = Convert.ToInt32 (Math.Sqrt (number));
for (int i = 2; i <= limit; i++) {
if (number % i == 0)
return false;
}
return true;
}
public void Start() {
mStop = false;
mWorker.Start();
}
public void Stop() {
mStop = true;
}
}
Le problème est que lorsque la file d'attente est vide, il consomme trop CPU (près de 98%). J'ai essayé AutoResetEvent d'informer les travailleurs que la file d'attente a été modifiée. Donc, ils attendent effectivement que ce signal se règle. Il a baissé le CPU à près de 0% mais je ne suis pas tout à fait sûr si c'est la meilleure méthode. Pouvez-vous suggérer une meilleure méthode pour garder les threads inactifs sans nuire à l'utilisation du processeur?
à l'aide d'un événement de remise à zéro va être la meilleure approche. –
Une autre possibilité est d'utiliser ThreadPool.QueueUserWorkItem –
Une autre est d'utiliser une minuterie pour vérifier la file d'attente et le feu de threads de travail. –