【问题标题】:Using await SemaphoreSlim.WaitAsync in .NET 4在 .NET 4 中使用 await SemaphoreSlim.WaitAsync
【发布时间】:2015-01-19 15:39:36
【问题描述】:

我的应用程序正在使用 .NET 4。我正在使用 await async,使用 nuget package

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

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

但是我得到以下编译错误。

“System.Threading.SemaphoreSlim”不包含“WaitAsync”的定义,并且找不到接受“System.Threading.SemaphoreSlim”类型的第一个参数的扩展方法“WaitAsync”(您是否缺少 using 指令或程序集参考?)

在 .NET 4.0 中是否可以使用 WaitAsync?

【问题讨论】:

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


    【解决方案1】:

    在其他两个答案中发布的 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);
        }
    }
    

    【讨论】:

      【解决方案2】:

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

      对于 .NET 4.0,您可以通过我的Nito.AsyncEx NuGet package 发送write your own async-compatible lockuse one

      【讨论】:

      • 您的第一个链接已失效,指向 GitHub AsyncEx 的 seconf 不再支持 .Net 4.0。
      • @sodjsn26fr:微软更改了第一个链接,如果您在 2020 年仍需要 .NET 4.0,则需要使用 NuGet 上仍然可用的旧版本 Nito.AsyncEx。跨度>
      • @Phil Jollans,谢谢。但我成功地尝试了“Phil Jollans”的回答。问候。
      【解决方案3】:

      WaitAsync 是在 .Net 4.5 中引入的。您要么需要通过查看source(不确定是否可能)将自己实现为扩展方法,要么可以使用 StephenToub 的AsyncSemaphore

      【讨论】:

        【解决方案4】:

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

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

        【讨论】:

        • 这不能与 Framework 4.0 一起编译,因为 Task.FromResult 没有定义。我已将 Task.FromResult(true) 替换为新的 TaskCompletionSource(true).Task。这可以编译,但我还没有测试过。
        • 我的简单更改没有奏效。我进行了不同的更改并将代码作为单独的答案发布。
        【解决方案5】:

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

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

        【讨论】:

          【解决方案6】:

          由于WaitAsync 在.NET 4.0 中不可用,您可以使用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); 
              }
          }
          

          【讨论】:

            猜你喜欢
            • 2012-02-24
            • 1970-01-01
            • 2016-03-15
            • 2012-09-07
            • 1970-01-01
            • 1970-01-01
            • 2017-03-28
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多