How to lock a block containing await operation in C#
Save below code in a file say AsyncLock.cs
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;
namespace namespaceName{// http://blogs.msdn.com/b/pfxteam/archive/2012/02/12/10266983.aspxpublic class AsyncSemaphore{private readonly static Task s_completed = Task.FromResult(true);private readonly Queue<TaskCompletionSource<bool>> m_waiters =new Queue<TaskCompletionSource<bool>>();
private int m_currentCount;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);}}// http://blogs.msdn.com/b/pfxteam/archive/2012/02/12/10266988.aspxpublic class AsyncLock{private readonly AsyncSemaphore m_semaphore;private readonly Task<Releaser> m_releaser;public AsyncLock(){m_semaphore = new AsyncSemaphore(1);m_releaser = Task.FromResult(new Releaser(this));}public Task<Releaser> LockAsync(){var wait = m_semaphore.WaitAsync();return wait.IsCompleted ?m_releaser :wait.ContinueWith((_, state) => new Releaser((AsyncLock)state),this, System.Threading.CancellationToken.None,TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);}public struct Releaser : IDisposable{private readonly AsyncLock m_toRelease;internal Releaser(AsyncLock toRelease) { m_toRelease = toRelease; }public void Dispose(){if (m_toRelease != null)m_toRelease.m_semaphore.Release();}}}}
now to use this in your project simply write below codes
AsyncLock asyncLock = new AsyncLock();Thats it. plain and simple.
using(var releaser = await asyncLock.LockAsync())
{
// awaitable tasks
}
Note:
Reference sites ->
http://blogs.msdn.com/b/pfxteam/archive/2012/02/12/10266988.aspx
http://blogs.msdn.com/b/pfxteam/archive/2012/02/12/10266983.aspx
http://sanjeev.dwivedi.net/?p=292
Comments
Post a Comment