Parallel Programming in .NET 4.0 - Part 2
This is the series of articles which focuses on new Parallel Programming concepts introduction and existing System.Threading namespace enhancements like Barrier, CountDownEvent etc. in .NET Framework 4.0. These series of article will bring in depth coverage of the Parallel Programming in .NET 4.0 and we can make use of it our day-to-day development activity. It will have working samples as attachment and code snippets as well for better understanding of Parallel Programming.
In part 2 of the article we cover the Barrier class and CountDownEvent classes. You can read the Part 1 of the series in dotnetgurukul.com.
Barrier:
Excerpt from MSDN: A barrier is a user-defined synchronization primitive that enables multiple threads (known as participants) to work concurrently on an algorithm in phases. Each participant executes until it reaches the barrier point in the code. The barrier represents the end of one phase of work. When a participant reaches the barrier, it blocks until all participants have reached the same barrier. After all participants have reached the barrier, you can optionally invoke a post-phase action. This post-phase action can be used to perform actions by a single thread while all other threads are still blocked. After the action has been executed, the participants are all unblocked.
We can take a real time example to brief about what's barrier. For an example, assume 12 people are travelling from Bangalore to New Delhi by 3 cars. They decided that they will be stopping in the following location (Hyderad, Nagpur, Agra and New Delhi) and wait for others to reach the same location. These points we can call it has Barriers. Whoever reaches there, they should wait and check whether all the team had arrived. If not arrived, they will be waiting till other team arrives that point.
.NET 4.0 Barrier works in the same way. We create threads and we add those Threads as participants to the Barrier. Once all the Threads have reached the Barrier, then it will continue executing the next steps. If any of them haven't reached the Barrier point, the other Threads will wait for the Thread to join hit the Barrier.
A small working example is given below.static void Main(string[] args)
{
int count = 0;
// Create a barrier with three participants
// Provide a post-phase action that will print out certain information
// And the third time through, it will throw an exception
System.Threading.Barrier barrier = new System.Threading.Barrier(3, (b) =>
{
Console.WriteLine("Post-Phase action: count={0}, phase={1}", count, b.CurrentPhaseNumber);
});
// Nope -- changed my mind. Let's make it five participants.
barrier.AddParticipants(2);
// Nope -- let's settle on four participants.
barrier.RemoveParticipant();
// This is the logic run by all participants
Action action = () =>
{
// This is thread safe way of increment the a variable.
Interlocked.Increment(ref count);
// Wait for other Threads to join here
barrier.SignalAndWait();
// After joining, do a increment again
Interlocked.Increment(ref count);
// Wait for other Threads to join here
barrier.SignalAndWait();
Interlocked.Increment(ref count);
barrier.SignalAndWait();
Interlocked.Increment(ref count);
barrier.SignalAndWait();
};
// Now launch 4 parallel actions to serve as 4 participants
Parallel.Invoke(action, action, action, action);
// It's good form to Dispose() a barrier when you're done with it.
barrier.Dispose();
}
CountDownEvent:
One of the common Asynchronous pattern in today's world I Fork/Join Parallelism. System.Threading.CountdownEvent type also helps with fork/join patterns, in particular for when dealing with concurrent programming models that don't provide built-in support for joins. The primary component of Fork/Join is to keep track of how many threads are still remaining to finish it's operations. We can achieve this in ManualResetEvent or AutoResetEvent in earlier versions of .NET Framework. However, CountDownEvent has an efficient fully managed implementation. How we can make use of CountDownEvent is given below.
1. Instantiate the CountDownEvent class with the number of counts that you want to wait on. E.g. given below
2. Call Signal() method in CountDownevent which will reduce the count
3. Call Wait() method to wait for all the Thread to get completes. It will wait till the count reaches 0 (Zero)
A simple working example is given below.static CountdownEvent _countdown = new CountdownEvent(3);
static void Main()
{
new Thread(DoSomeThing).Start("Thread 1");
new Thread(DoSomeThing).Start("Thread 2");
new Thread(DoSomeThing).Start("Thread 3");
// It will wait till the count reaches 0
_countdown.Wait();
Console.WriteLine("All threads have finished!");
}
static void DoSomeThing(object thing)
{
Thread.Sleep(2000);
Console.WriteLine(thing);
// This will decrement the count
_countdown.Signal();
}
Hope it gives a introduction about Barrier class and CountDownEvent class. In next part of the article, Parallel Extensions will be covered in detail.
A sample solution containing 2 project, one for Barrier and one for CountDownEvent is attached. You can download and run the application.