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.
WaitHandle
is the same as a condition variable leads to misunderstandings like #18277444 –
Naissant waithHandle.Wait();mutex.WaitOne();try{...}finally{mutex.ReleaseMutex();}
... –
Operator WaitHandle
. But a condition variable is far more powerful. –
Naissant 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
lock
:) –
Disesteem 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();
}
}
}
}
© 2022 - 2024 — McMap. All rights reserved.