2010-10-06 3 views
0

Tenir compte de l'extrait de test suivant:Comment puis-je garantir un résultat déterministe pour ce problème de multithreading?

 // act 
     AutoResetEvent workDoneEvent = new AutoResetEvent(false); 
     ThreadPool.QueueUserWorkItem(delegate 
             { 
              ProcessAndSignal(processor, workDoneEvent); 
             }, null); 

     // let worker thread have a go 
     workDoneEvent.WaitOne(); 
     blockingFetcher.WaitForNextMessage = false; 

     // assert 
     Assert.That(processor.StopCause, Is.Null); 
    } 

    private static void ProcessAndSignal(MessageProcessor processor, AutoResetEvent workDoneEvent) 
    { 
     workDoneEvent.Set(); 
     // this invocation will block until the WaitForNextMessageFlag is set 
     processor.ProcessMessages(); 
    } 

scénario idéal:

  1. ProcessAndSignalMethod est mis en attente sur le pool de threads, mais ne démarre pas à exécuter.
  2. Les principaux blocs de filetage (autoResetEvent.WaitOne())
  3. Un thread de travail commence à exécuter le procédé « ProcessAndSignal »
  4. Les threads de travail a suffisamment de temps pour signaler le drapeau et lancer l'exécution de la méthode ProcessMessages
  5. Le thread principal est réinjecté dans la vie et définit la propriété qui provoquera l'achèvement de la méthode ProcessAndSignal

Le scénario suivant peut-il se produire?

1) ProcessAndSignal() commencera à exécuter avant le thread principal définit le AutoResetEvent à WaitOne() qui provoquera un blocage (les processor.ProcessMessages() va entrer dans une boucle de infinitif)

Répondre

1

Oui, la scénario peut se produire. Oui, il peut se bloquer si vous ne déclarez pas la variable bool volatile. N'utilisez pas un bool, utilisez un événement comme vous l'avez fait. La logique semble bizarre, il semble que vous essayez de laisser le thread principal attendre que le traitement soit terminé. Le workDoneEvent ne signale pas réellement que le travail a été fait. En ce moment, le thread principal va vérifier l'affirmer avant le travailleur est fait, cela ne peut pas être bon. Si l'intention était qu'elle signale que le travail est terminé alors ProcessAndSignal devrait être celui qui appelle Set(), à la fin de la méthode. Et le thread principal devrait appeler WaitOne().

Si cela est exact, alors vous ne devriez pas utiliser QUWI, il suffit d'appeler directement ProcessAndSignal sans utiliser de thread. Far plus efficace, aucune chance pour les problèmes de threading.

Questions connexes