2010-03-25 15 views

Odpowiedz

18

Musisz sam to sprawdzić.

Jedną z opcji jest to, aby użyć licznika i zdarzenia Reset:

int toProcess = 10; 
using(ManualResetEvent resetEvent = new ManualResetEvent(false)) 
{ 
    var list = new List<int>(); 
    for(int i=0;i<10;i++) list.Add(i); 
    for(int i=0;i<10;i++) 
    { 
     ThreadPool.QueueUserWorkItem(
      new WaitCallback(x => { 
       Console.WriteLine(x); 
       // Safely decrement the counter 
       if (Interlocked.Decrement(ref toProcess)==0) 
       resetEvent.Set(); 

      }),list[i]); 
    } 

    resetEvent.WaitOne(); 
} 
// When the code reaches here, the 10 threads will be done 
Console.WriteLine("Done"); 
+0

lol. Myślę, że "zrobione" jest lepszym imieniem, które 'mre' chociaż –

+0

@Remus: to lepiej? –

+0

Oczywiście to robi różnicę;) –

8

nie jestem pewien, czy pula wątków naraża taką funkcjonalność, ale można użyć czekać uchwytów i przy okazji Iteracja dwukrotnie wydaje zbędne:

var events = new ManualResetEvent[10]; 
var list = new List<int>(); 
for (int i = 0; i < 10; i++) 
{ 
    list.Add(i); 
    events[i] = new ManualResetEvent(false); 
    int j = i; 
    ThreadPool.QueueUserWorkItem(x => { 
     Console.WriteLine(x); 
     events[j].Set(); 
    }, list[i]); 
} 
WaitHandle.WaitAll(events); 
+0

+1 - to samo rozwiązanie, co napisałem; tylko ty byłeś szybszy i przedstawiłeś nieco bardziej elegancki kod. –

+0

OK, byłeś też szybszy ode mnie. – Timores

+8

Po prostu ostrzeżenie z tym ... WaitHandle.WaitAll zawiedzie, jeśli masz więcej niż 64 elementy w wątku STA ... –

1

Pula wątków nie informuje o zakończeniu wykonywania wątku, więc element pracy musi wykonać to sam. Zmieniłem kod w ten sposób:

var list = new List<int>(); 
    ManualResetEvent[] handles = new ManualResetEvent[10]; 
    for (int i = 0; i < 10; i++) { 
     list.Add(i); 
     handles[i] = new ManualResetEvent(false); 
    } 
    for (int i = 0; i < 10; i++) { 
     ThreadPool.QueueUserWorkItem(
     new WaitCallback(x => 
     { 
      Console.WriteLine(x); 
      handles[(int) x].Set(); 
     }), list[i]); 
    } 

    WaitHandle.WaitAll(handles); 
0

Tak to zrobię.

class Program 
{ 
    static void Main(string[] args) 
    { 
     var items = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; 
     using (var countdown = new Countdown(items.Length)) 
     { 
      foreach (var item in items) 
      { 
       ThreadPool.QueueUserWorkItem(o => 
       { 
        Thread.SpinWait(100000000); 
        Console.WriteLine("Thread Done!"); 
        countdown.Signal(); 
       }); 
      } 
      countdown.Wait(); 
     } 
     Console.WriteLine("Job Done!"); 
     Console.ReadKey(); 
    } 

    public class Countdown : IDisposable 
    { 
     private readonly ManualResetEvent done; 
     private readonly int total; 
     private volatile int current; 

     public Countdown(int total) 
     { 
      this.total = total; 
      current = total; 
      done = new ManualResetEvent(false); 
     } 

     public void Signal() 
     { 
      lock (done) 
      { 
       if (current > 0 && --current == 0) 
        done.Set(); 
      } 
     } 

     public void Wait() 
     { 
      done.WaitOne(); 
     } 

     public void Dispose() 
     { 
      done.Dispose(); 
     } 
    } 
} 
+0

Byłoby bardziej wydajne przy użyciu opcji Interlocked.Decrement zamiast blokady. Zobacz moją odpowiedź na odpowiedni kod. –

+0

Wywołanie done.Dispose() w Odliczanie jest nieprawidłowe, daje "niedostępne ze względu na poziom ochrony". Należy to zrobić. Zamknij() jako Zamknij i Usuń są równoważne. – AceJordin

11

W .NET Framework 4+ używać poręczny klasę System.Threading.CountdownEvent:

const int threadCount = 10; 
var list = new List<int>(threadCount); 
for (var i = 0; i < threadCount; i++) list.Add(i); 

using (var countdownEvent = new CountdownEvent(threadCount)) 
{ 
    for (var i = 0; i < threadCount; i++) 
     ThreadPool.QueueUserWorkItem(
      x => 
      { 
       Console.WriteLine(x); 
       countdownEvent.Signal(); 
      }, list[i]); 

    countdownEvent.Wait(); 
} 
Console.WriteLine("done"); 
Powiązane problemy