Condition variables in C# [closed]

左心房为你撑大大i 提交于 2019-12-01 03:33:13

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.

System.Threading.Monitor is one way (example within)

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#:

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

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();
            }
        }
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!