我正在学习任务并行库(与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解决方案是什么?
答案 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();
}
}
}