AutoResetEvent won't do it because it because it only signals *one* of the waiting threads, not *all* of them. What you need is a manual reset event and some complex handling.
I give you BarrierHandle:
using System;
using System.Threading;
class SpectralNorm
{
public class BarrierHandle : System.Threading.WaitHandle
{
int current;
int threads;
ManualResetEvent handle = new ManualResetEvent (false);
public BarrierHandle (int threads)
{
this.current = threads;
this.threads = threads;
}
public override bool WaitOne()
{
ManualResetEvent h = handle;
if (Interlocked.Decrement (ref current) > 0) {
h.WaitOne ();
}
else {
handle = new ManualResetEvent (false);
Interlocked.Exchange (ref current, threads);
h.Set ();
h.Close ();
}
return true;
}
}
public static void Main(String[] args)
{
int threadCount = 5;//Environment.ProcessorCount;
// Lets assume that there's 20 units of data for each thread
int[] dataset = new int [threadCount * 20];
// This is the handle we use to ensure all threads complete the current step
// before continuing to the next step
BarrierHandle barrier = new BarrierHandle(threadCount);
// Fire up the threads
for (int i = 0; i < threadCount; i++) {
ThreadPool.QueueUserWorkItem (delegate {
int jjj = i;
try {
Step1 (dataset, jjj * 20, 20);
barrier.WaitOne ();
Step2 (dataset, jjj * 20, 20);
barrier.WaitOne ();
Step3 (dataset, jjj * 20, 20);
} catch (Exception ex) {
Console.WriteLine (ex);
}
});
}
System.Threading.Thread.Sleep (3000);
}
private static void Step1 (int[] array, int offset, int count)
{
Console.WriteLine ("Step1: {0} - {1}", offset, offset + count);
Thread.Sleep (500);
}
private static void Step2 (int[] array, int offset, int count)
{
Console.WriteLine ("Step2: {0} - {1}", offset, offset + count);
Thread.Sleep (500);
}
private static void Step3 (int[] array, int offset, int count)
{
Console.WriteLine ("Step3: {0} - {1}", offset, offset + count);
Thread.Sleep (500);
}
}
1 comments:
There is CountdownEvent class in ParallelFx which can be used for that.
Post a Comment