在.NET 4中使用等待SemaphoreSlim.WaitAsync

时间:2015-01-19 15:39:37

标签: c# .net-4.0 semaphore async-await

我的应用程序使用的是.NET 4.我正在使用nuget package

等待异步

在我的应用程序中,我想对sempahore WaitAsync调用进行等待,如下所示。

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

但是我遇到了编译错误。

  
    

'System.Threading.SemaphoreSlim'不包含'WaitAsync'的定义,并且没有可以找到接受类型为'System.Threading.SemaphoreSlim'的第一个参数的扩展方法'WaitAsync'(你是否缺少using指令或汇编参考?)

  

在.NET 4.0中,无论如何都可以使用uisng WaitAsync吗?

6 个答案:

答案 0 :(得分:5)

您无法在.Net 4.0中使用SemaphoreSlim.WaitAsync,因为此方法已添加到.Net 4.5中的SemaphoreSlim

然后,您可以在Building Async Coordination Primitives, Part 5: AsyncSemaphore中跟随Stephen Toub的示例实现您自己的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);
    }
}

答案 1 :(得分:3)

正如其他人所提到的,.NET 4.5引入了SemaphoreSlim.WaitAsync

对于.NET 4.0,您可以write your own async-compatible lock中的use oneNito.AsyncEx NuGet package

答案 2 :(得分:2)

.Net 4.5引入了

WaitAsync。您需要通过查看source(不确定是否可能)来实现自己作为扩展方法,或者您可以使用StephenToub的AsyncSemaphore

答案 3 :(得分:1)

不,你需要升级到.NET 4.5(或者自己写一个WaitAsync扩展名(或固有的异步信号量))。

.NET 4.0的异步扩展允许支持实际的await关键字。 .NET 4.5的大部分工作是向可以等待的各种BCL类型添加异步操作。如果您需要这些操作,则需要升级您使用的框架版本。

答案 4 :(得分:1)

作为{{1&#39;在.NET 4.0中可用,您可以使用Stephan Toub's series of async synchronization primitives中的代码:

WaitAsync

答案 5 :(得分:0)

在另外两个答案中发布的类AysncSemaphore不能与Framework 4.0一起编译,因为未定义Task.FromResult。

这是我的替代版本:

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