Rendezvous Thread Synchronization
I am currently implementing Reservation (a pattern for “partial temporary commitment” when using Sagas).The implementation calls for calling a few of the saga members asking them to reserve an asset. Since network calls can take some time I wanted to make each call on its own thread, collect any errors (failures to reserve or communication exceptions) and then have all the threads reconverge to the initiating thread where any problems will be sorted out (e.g. by retrying the reservation). It basically looks something like the figure below:
As you can probably guess this type of synchronization is called Rendezvous (as the threads “meet”). It is also actually fairly easy to implement in .NET I usually do something along the lines of the code snippet below and things like Parallel.For in C# 4.0 will give a similar effect
- private void DispatchThreads(List<Thread> threads, List<SharedContext> sharedContexts, ParameterizedThreadStart threadFunction)
- {
- //initiate threads
- foreach (var context in sharedContexts)
- {
- var dispatchThread = new Thread(threadFunction);
- threads.Add(dispatchThread);
- dispatchThread.Start(context);
- }
-
- //Rendezvous
- foreach (var dispatchThread in threads)
- dispatchThread.Join();
-
- \
However, that’s not why I am writing this post. It turns out I have a more complicated situation. In my setup the code of “Main Thread” (in the figure above) can be run by multiple different threads which are initiated by external events (i.e. I don’t control when they run) – What I needed to to is to make sure that if there are several threads that run in parallel they need to wait for the last of them to finish one section of the code before they can all move on. To explain this better consider the figure below:
Thread 1 starts, sometime after that Thread 2 starts and then Thread 3 starts as well – Thread 1 and Thread 2 have to hold and wait until Thread 3 finished. Thread 4 starts beyond the Rendezvous so none of the other threads care about it. Had it started just before Thread 3 finished all the threads would have had to wait for it as well. Basically I need a similar effect to chords in polyphonic C#
I couldn’t find anything that .NET 3.5 for this - It is kind of what ManualResetEvent – however, it not quite that, since we need to wait for the event only when we’re done. Also we need to let other threads “know” we are running so that they’d wait for us. So indeed I wrapped a ManualResetEvent with a few methods to do just that and ended up with the following.
- public class Rendezvous
- {
- private readonly ManualResetEvent Synch = new ManualResetEvent(true);
- private readonly object Locker = new object();
- private int Counter = 0;
-
-
- /// <summary>
- /// Join the Rendezvous - Mark that a thread is active and it should finish before the others can continue
- /// </summary>
- public void MarkStart()
- {
- lock (Locker)
- {
- if (Counter < 0) Counter = 0;
- Counter++;
- Synch.Reset();
- }
- }
-
- /// <summary>
- /// Allows a thread to wait for others without having the others wait for it
- /// </summary>
- public void Wait()
- {
- Synch.WaitOne();
- }
-
- /// <summary>
- ///
- /// </summary>
- public void MarkFinishAndWait()
- {
- lock (Locker)
- {
- if (--Counter <= 0) Synch.Set();
- }
- //it is ok if we context switch and lock since we want to synchronize the end times
- Wait();
- }
- \
As long as all the threads have access to the same instance of the Rendezvous class they can synchronize their end times.
Rendezvous is a common pattern for workflow systems (also known as Join-And). It is the first time I had to do that in C# with uncontrolled/uncoordinated thread starts so I don’t know how useful it would be to you. However I thought it is also interesting reading so I published it anyway :)

