c# - 条件变量的 TPL 等价物是什么?

标签 c# .net asynchronous task-parallel-library async-await

我正在学习任务并行库(结合 C# 5.0 async/await),我想做这样的事情:

public class Foo
{
    public void UnblockDoSomething()
    {
        DoWork();
        // notify DoSomethingAsync
    }

    public async Task DoSomethingAsync()
    {
        DoSomeWork();
        await ... // Wait until UnblockDoSomething is called
        DoMoreWork();
    }
}

在传统的线程模型中,我可以使用条件变量来完成此操作。这个问题的 TPL 解决方案是什么?

最佳答案

如果你只有一次一个通知,你可以使用TaskCompletionSource:

public class Foo
{
  private TaskCompletionSource<object> _signal = new TaskCompletionSource<object>();

  public void UnblockDoSomething()
  {
    DoWork();
    _signal.SetResult(null);
    _signal = new TaskCompletionSource<object>();
  }

  public async Task DoSomethingAsync()
  {
    var continueSignal = _signal.Task;
    DoSomeWork();
    await continueSignal;
    DoMoreWork();
  }
}

另一种选择是使用信号量 (SemaphoreSlim),如果之前收到过信号,它将“记住”:

public class Foo
{
  private readonly SemaphoreSlim _mutex = new SemaphoreSlim(0);

  public void UnblockDoSomething()
  {
    DoWork();
    _mutex.Release();
  }

  public async Task DoSomethingAsync()
  {
    DoSomeWork();
    await _mutex.WaitAsync();
    DoMoreWork();
  }
}

如果你真的需要一个条件变量,你可以使用AsyncConditionVariable来 self 的 AsyncEx library :

public class Foo
{
  private readonly AsyncLock _mutex = new AsyncLock();
  private readonly AsyncConditionVariable _cv = new AsyncConditionVariable(_mutex);

  public void UnblockDoSomething()
  {
    using (await _mutex.LockAsync())
    {
      DoWork();
      _cv.Notify();
    }
  }

  public async Task DoSomethingAsync()
  {
    using (await _mutex.LockAsync())
    {
      DoSomeWork();
      await _cv.WaitAsync();
      DoMoreWork();
    }
  }
}

关于c# - 条件变量的 TPL 等价物是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16656538/

相关文章:

JavaScript OOP 和 Chrome 扩展 api 中的异步方法

c# - 具有 System.Windows.Forms 和自定义基类的自定义 WinForms 控件

c# - 运行时本地化

C# StreamReader 关闭 - 内存泄漏?

c# - 如何使用 IList 上的 LINQ 扩展来查询嵌套对象中的值?

java - 如何使用 Spring boot 构建非阻塞异步 Web 服务

javascript - Node.js - 为什么我的一些回调没有异步执行?

c# - AcquireTokenAsync 仅在控制台应用程序中工作

c# - 我应该在我的 IOC 容器中注册哪些类型来实例化 Umbraco ContentService?

c# - 如何将 Blazor 包含到现有项目中?