The AysncSemaphore class published in the other two answers does not compile with Framework 4.0, because Task.FromResult is not defined.
This is my alternate version:
public class AsyncSemaphore { private readonly static Task s_completed ; private readonly Queue<TaskCompletionSource<bool>> m_waiters = new Queue<TaskCompletionSource<bool>>(); private int m_currentCount; static AsyncSemaphore() { var tcs = new TaskCompletionSource<bool>(); tcs.SetResult(true); s_completed = tcs.Task ; } public AsyncSemaphore(int initialCount) { if (initialCount < 0) throw new ArgumentOutOfRangeException("initialCount"); m_currentCount = initialCount; } public Task WaitAsync() { lock (m_waiters) { if (m_currentCount > 0) { --m_currentCount; return s_completed; } else { var waiter = new TaskCompletionSource<bool>(); m_waiters.Enqueue(waiter); return waiter.Task; } } } public void Release() { TaskCompletionSource<bool> toRelease = null; lock (m_waiters) { if (m_waiters.Count > 0) toRelease = m_waiters.Dequeue(); else ++m_currentCount; } if (toRelease != null) toRelease.SetResult(true); } }
source share