5

asyncTask Parallel Library (C# 5.0 /と組み合わせてawait) を学習しており、次のようなことをしたいと考えています。

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

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

従来のスレッド モデルでは、条件変数を使用してこれを実現できます。この問題に対する TPL ソリューションは何ですか?

4

1 に答える 1

14

一度に 1 つずつ通知がある場合は、次を使用できます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、私のAsyncEx ライブラリから使用できます。

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();
    }
  }
}
于 2013-05-20T19:09:59.783 に答える