Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using await SemaphoreSlim.WaitAsync in .NET 4

My application is using .NET 4. I am using await async using nuget package

In my application I want to do an await on sempahore WaitAsync call as follows.

SemaphoreSlim semphore = new SemaphoreSlim(100);
await semphore.WaitAsync();

However I am getting following compilation error.

'System.Threading.SemaphoreSlim' does not contain a definition for 'WaitAsync' and no extension method 'WaitAsync' accepting a first argument of type 'System.Threading.SemaphoreSlim' could be found (are you missing a using directive or an assembly reference?)

Could there be anyway of uisng WaitAsync in .NET 4.0?

like image 562
whoami Avatar asked Jan 19 '15 15:01

whoami


2 Answers

You can't use SemaphoreSlim.WaitAsync in .Net 4.0 since this method was added to SemaphoreSlim in .Net 4.5.

You can however implement your own AsyncSemaphore following Stephen Toub's example in Building Async Coordination Primitives, Part 5: AsyncSemaphore:

public 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);
    }
}
like image 193
i3arnon Avatar answered Oct 14 '22 12:10

i3arnon


As others have mentioned, .NET 4.5 introduced SemaphoreSlim.WaitAsync.

For .NET 4.0, you can either write your own async-compatible lock or use one from my Nito.AsyncEx NuGet package.

like image 22
Stephen Cleary Avatar answered Oct 14 '22 13:10

Stephen Cleary