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

时间:2013-05-20 19:03:58

标签: 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解决方案是什么?

1 个答案:

答案 0 :(得分:11)

如果您只是一次一个通知,则可以使用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),它将记住&#34;记住&#34;如果之前曾发出信号:

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中的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();
    }
  }
}