This recipe illustrates another interesting synchronization construct called Barrier. The Barrier construct helps to organize several threads so that they meet at some point in time, providing a callback that will be executed each time the threads call the SignalAndWait method.
Getting ready
To step through this recipe, you will need Visual Studio 2015. There are no other prerequisites. The source code for this recipe can be found at BookSamples\Chapter2\Recipe7.
How to do it...
To understand the use of the Barrier construct, perform the following steps:
Start Visual Studio 2015. Create a new C# console application project.
In the Program.cs file, add the following using directives:
using System;
using System.Threading;
using static System.Console;
using static System.Threading.Thread;
Below the Main method, add the following code:
static Barrier _barrier = new Barrier(2,
b => WriteLine($"End of phase {b.CurrentPhaseNumber + 1}"));
static void PlayMusic(string name, string message, int seconds)
{
for (int i = 1; i < 3; i++)
{
WriteLine("----------------------------------------------");
Sleep(TimeSpan.FromSeconds(seconds));
WriteLine($"{name} starts to {message}");
Sleep(TimeSpan.FromSeconds(seconds));
WriteLine($"{name} finishes to {message}");
_barrier.SignalAndWait();
}
}
Inside the Main method, add the following code:
var t1 = new Thread(() => PlayMusic("the guitarist", "play an amazing solo", 5));
var t2 = new Thread(() => PlayMusic("the singer", "sing his song", 2));
t1.Start();
t2.Start();
Run the program.
How it works...
We create a Barrier construct, specifying that we want to synchronize two threads, and after each of those two threads call the _barrier.SignalAndWait method, we need to execute a callback that will print out the number of phases completed.
Each thread will send a signal to Barrier twice, so we will have two phases. Every time both the threads call the SignalAndWait method, Barrier will execute the callback. It is useful for working with multithreaded iteration algorithms, to execute some calculations on each iteration end. The end of the iteration is reached when the last thread calls the SignalAndWait method.