10

C# 中是否使用了条件变量和监视器?

有人可以给我一个例子吗?

4

5 回答 5

14

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

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

于 2009-12-31T16:50:59.817 回答
4

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

于 2009-12-31T16:41:26.400 回答
3

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

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

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

于 2009-12-31T16:39:39.620 回答
2

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

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

Vista/Server 2008 条件变量的 .NET 包装器

于 2011-02-08T20:18:31.013 回答
0

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();
            }
        }
    }
}
于 2014-11-01T13:52:46.720 回答