Are condition variables & monitors used in C#?
Can someone give me an example?
Are condition variables & monitors used in C#?
Can someone give me an example?
The equivalent of a condition variable that you use just for signaling in .NET is the abstract WaitHandle class. Practical implementations of it are the ManualResetEvent and AutoResetEvent classes.
A condition variable that you use as a monitor requires System.Threading.Monitor. The C# lock
statement makes it very easy to use, it ensures the monitor is always exited without explicitly programming the Exit() call.
You can use the Lock object which acts as syntactic sugar for the Monitor class.
lock(someObject)
{
// Thread safe code here.
}
http://msdn.microsoft.com/en-us/library/c5kehkcz%28VS.80%29.aspx
As an alternative to ManualResetEvent and friends, Windows now provides native support for condition variables. I haven't benchmarked it myself, but there's a good chance your performance will improve when leveraging the native API.
Here's a Code Project article that explains how to access this (relatively new) construct from C#:
This version atomically unlocks a Mutex or ReaderWriterLockSlim while waiting for signalling, and relocks it before returning - which is the posix way.
using System.Collections.Concurrent;
namespace System.Threading.More {
public class ConditionVariable {
private readonly ConcurrentQueue<ManualResetEventSlim> _waitingThreads = new ConcurrentQueue<ManualResetEventSlim>();
/// <summary>
/// Atomically unlocks and waits for a signal.
/// Then relocks the mutex before returning
/// </summary>
/// <param name="mutex"></param>
public void Wait(Mutex mutex) {
if (mutex == null) {
throw new ArgumentNullException("mutex");
}
var waitHandle = new ManualResetEventSlim();
try {
_waitingThreads.Enqueue(waitHandle);
mutex.ReleaseMutex();
waitHandle.Wait();
} finally {
waitHandle.Dispose();
}
mutex.WaitOne();
}
public void WaitRead(ReaderWriterLockSlim readerWriterLock) {
if (readerWriterLock == null) {
throw new ArgumentNullException("readerWriterLock");
}
var waitHandle = new ManualResetEventSlim();
try {
_waitingThreads.Enqueue(waitHandle);
readerWriterLock.ExitReadLock();
waitHandle.Wait();
} finally {
waitHandle.Dispose();
}
readerWriterLock.EnterReadLock();
}
public void Signal() {
ManualResetEventSlim waitHandle;
if (_waitingThreads.TryDequeue(out waitHandle)) {
waitHandle.Set();
}
}
public void Broadcast() {
ManualResetEventSlim waitHandle;
while (_waitingThreads.TryDequeue(out waitHandle)) {
waitHandle.Set();
}
}
}
}