Using await SemaphoreSlim.WaitAsync in .NET 4

感情迁移 提交于 2019-12-06 03:24:57

问题


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?


回答1:


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);
    }
}



回答2:


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.




回答3:


WaitAsync is introduced with .Net 4.5. You either need to implement yourself as an extension method by looking into source(not sure if that is possible), or you can use StephenToub's AsyncSemaphore.




回答4:


No, you'll need to upgrade to .NET 4.5 (or write a WaitAsync extension (or inherently asynchronous semaphore) yourself).

The async extensions for .NET 4.0 are there to allow for the support of the actual await keyword. Much of the work of .NET 4.5 is adding asynchronous operations to various BCL types that can be awaited. If you need those operations, you'll need to upgrade the version of the framework you use.




回答5:


As the WaitAsync isn't avaliable in .NET 4.0, You can use the code from Stephan Toub's series of async synchronization primitives:

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); 
    }
}



回答6:


The class AysncSemaphore, posted in two other answers, does not compile with Framework 4.0, because Task.FromResult is not defined.

This is my alternative 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);
    }
}


来源:https://stackoverflow.com/questions/28028262/using-await-semaphoreslim-waitasync-in-net-4

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