2010-03-23 2 views
3

L'exemple de file d'attente de threading "Accelerated C# 2008" (classe CrudeThreadPool) ne fonctionne pas correctement. Si j'insère un travail long dans WorkFunction() sur une machine à 2 processeurs s'exécutant pour la tâche suivante, ne pas s'exécuter avant la fin du premier. Comment résoudre ce problème? Je veux charger le processeur à 100 pour centProblèmes liés à ThreadQueue dans "Accelerated C# 2008"

public class CrudeThreadPool 
{ 
    static readonly int MAX_WORK_THREADS = 4; 
    static readonly int WAIT_TIMEOUT = 2000; 
    public delegate void WorkDelegate(); 

    public CrudeThreadPool() 
    { 
     stop = 0; 
     workLock = new Object(); 
     workQueue = new Queue(); 
     threads = new Thread[MAX_WORK_THREADS]; 
     for (int i = 0; i < MAX_WORK_THREADS; ++i) 
     { 
      threads[i] = new Thread(new ThreadStart(this.ThreadFunc)); 
      threads[i].Start(); 
     } 

    } 


    private void ThreadFunc() 
    { 
     lock (workLock) 
     { 
      int shouldStop = 0; 
      do 
      { 
       shouldStop = Interlocked.Exchange(ref stop, stop); 
       if (shouldStop == 0) 
       { 
        WorkDelegate workItem = null; 

        if (Monitor.Wait(workLock, WAIT_TIMEOUT)) 
        { 
         // Process the item on the front of the queue 
         lock (workQueue) 
         { 
          workItem = (WorkDelegate)workQueue.Dequeue(); 
         } 
         workItem(); 
        } 
       } 
      } while (shouldStop == 0); 
     } 
    } 

    public void SubmitWorkItem(WorkDelegate item) 
    { 
     lock (workLock) 
     { 

      lock (workQueue) 
      { 
       workQueue.Enqueue(item); 
      } 
      Monitor.Pulse(workLock); 
     } 
    } 

    public void Shutdown() 
    { 
     Interlocked.Exchange(ref stop, 1); 
    } 
    private Queue workQueue; 
    private Object workLock; 
    private Thread[] threads; 
    private int stop; 
} 

public class EntryPoint 
{ 
    static void WorkFunction() 
    { 
     Console.WriteLine("WorkFunction() called on Thread 0}", Thread.CurrentThread.GetHashCode()); 
     //some long job 
     double s = 0; 
     for (int i = 0; i < 100000000; i++) 
      s += Math.Sin(i); 
    } 

    static void Main() 
    { 
     CrudeThreadPool pool = new CrudeThreadPool(); 
     for (int i = 0; i < 10; ++i) 
     { 
      pool.SubmitWorkItem(
      new CrudeThreadPool.WorkDelegate(EntryPoint.WorkFunction)); 
     } 
     pool.Shutdown(); 
    } 
} 
+0

BTW, MAX_WORK_THREADS et WAIT_TIMEOUT devrait pas être en lecture seule, mais const – abatishchev

Répondre

4

je peux voir 2 problèmes:

  • intérieur ThreadFunc() vous prenez un lock(workLock) pendant toute la durée de la méthode, qui signifie que votre threadpool n'est plus async. Dans la méthode Main(), vous fermez le pool de threads sans attendre que le processus se termine.

  • Assez curieusement, c'est pourquoi cela fonctionne maintenant, en arrêtant chaque ThreadFunc après 1 boucle.

0

Il est difficile de dire parce qu'il n'y a pas de retrait, mais il me semble que cela l'exécution de l'élément de travail tout en maintenant workLock - qui va essentiellement sérialiser tout le travail .

Dans la mesure du possible, je vous suggère de commencer à utiliser le framework Parallel Extensions dans .NET 4, qui a évidemment passé un peu plus de temps dessus. Sinon, il y a le pool de threads existant dans le framework, et il y a d'autres implémentations autour si vous voulez jeter un oeil. J'en ai un en MiscUtil même si je n'ai pas regardé le code depuis un bon moment - c'est plutôt primitif.

+0

si seulement nos employeurs nous ont permis de choisir le nouveau cadre, le moment où il a été libéré. Dans le monde réel, nous devons nous soucier de prendre en charge les machines de spécifications min et les anciens systèmes d'exploitation qui peuvent ou non être pris en charge par .net 4 – trampster

Questions connexes