2016-12-14 4 views
1

Ich schreibe ein C# -Programm, das Multithreading und Synchronisation zwischen mehreren Threads beinhaltet. Die Threads müssen alle iterative Aufgaben unabhängig voneinander ausführen. Nachdem ein Thread eine bestimmte Anzahl von Iterationen beendet hat, muss er auf die anderen Threads warten. Nachdem alle von ihnen die Anzahl der Iterationen angegeben und ein Zwischenergebnis erhalten haben, sollten sie einige synchronisierte Arbeiten durchführen und dann die Ausführung fortsetzen, bis ein anderer Synchronisationspunkt erreicht ist und so weiter.C# Warten Sie auf Signale von allen Threads, bevor Sie fortfahren

Hier ist mein Versuch, dieses (ein Thread nach nur einer Iteration unterbrechen sollte, dann für die anderen warten) zu erreichen:

int nThreads = Environment.ProcessorCount; 
Thread[] threads = new Thread[nThreads]; 

ManualResetEvent[] manualResetEvents = new ManualResetEvent[nThreads]; 
for (int i = 0; i < nThreads; i++) 
{ 
    manualResetEvents[i] = new ManualResetEvent(false); 
} 

int nSteps = 5; 
Random rnd = new Random(); 
for (int i = 0; i < nThreads; i++) 
{ 
    int idx = i; 
    threads[i] = new Thread(delegate() 
    { 
     int cStep = nSteps; 

     while (cStep > 0) 
     { 
      manualResetEvents[idx].Reset(); 
      Console.Write("\nThread {0} working... cStep = {1}\n", idx, cStep); 

      Thread.Sleep(rnd.Next(1000)); 

      manualResetEvents[idx].Set(); 
      Console.WriteLine("\nThread {0} work done. Waiting Others...cStep = {1}\n", idx, cStep); 

      WaitHandle.WaitAll(manualResetEvents); 
      cStep--; 
     } 

    }); 
} 

for (int i = 0; i < nThreads; i++) 
{ 
    threads[i].Start(); 

} 

for (int i = 0; i < nThreads; i++) 
{ 
    threads[i].Join(); 
} 

Aber der Code oben scheint nicht funktioniert, denn nicht irgendwelchen Thread wartet auf alle der anderen Threads, um aus irgendeinem Grund eine Iteration durchzuführen. Ich denke, ich missverstehe den Zweck von ManualResetEvent oder benutze es falsch, was kannst du vorschlagen?

Antwort

2

Ihr Code ist anfällig für Race-Bedingungen. Nachdem alle Threads die erste Iteration abgeschlossen haben, werden alle Ereignisse noch festgelegt. Wenn dann ein einzelner Thread die Schleife durchläuft, bevor die anderen ihre Ereignisse zurücksetzen, werden die anderen Ereignisse weiterhin festgelegt, und Sie hören früh auf zu warten.

Es gibt viele Möglichkeiten, diesen Fehler zu beheben, aber die beste Lösung für Sie ist System.Threading.Barrier. Es ist explizit für diese Situation konzipiert, in der mehrere Threads durch einen mehrstufigen Algorithmus parallel arbeiten sollen.

+0

Vielen Dank für die Hilfe, ich habe dieses Problem bereits mit der erwähnten Barriere-Klasse gelöst. – user3808059

Verwandte Themen