C#中的条件变量

时间:2009-12-31 16:37:13

标签: c# multithreading monitor

是条件变量& C#中使用的监视器?

有人可以举个例子吗?

5 个答案:

答案 0 :(得分:13)

在.NET中仅用于信令的条件变量的等价物是抽象的WaitHandle类。它的实际实现是ManualResetEvent和AutoResetEvent类。

用作监视器的条件变量需要System.Threading.Monitor。 C#lock语句使其易于使用,它确保始终退出监视器而无需显式编程Exit()调用。

答案 1 :(得分:4)

System.Threading.Monitor是一种方式(例如)

答案 2 :(得分:3)

您可以使用Lock对象作为Monitor类的语法糖。

lock(someObject)
{
    // Thread safe code here.
}

http://msdn.microsoft.com/en-us/library/c5kehkcz%28VS.80%29.aspx

答案 3 :(得分:2)

作为ManualResetEvent和朋友的替代方案,Windows现在为条件变量提供native support。我自己没有对它进行基准测试,但在利用本机API时,您的性能很可能会提高。

这是一篇Code Project文章,解释了如何从C#访问这个(相对较新的)构造:

A .NET Wrapper for the Vista/Server 2008 Condition Variable

答案 4 :(得分:0)

这个版本在等待信号时原子地解锁Mutex或ReaderWriterLockSlim,并在返回之前重新锁定它 - 这是posix方式。

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();
            }
        }
    }
}