在任何时候,我都可以接收一个需要长时间运行才能满足的方法调用。
这些方法有以下几种。因为它们共享一个资源,所以它们不能同时运行是很重要的 - 每个都应该按顺序运行。
通常情况下,我只是按顺序拨打电话:
var result1 = await Foo1Async();
var result2 = await Foo2Async();
但是,在这种情况下,对我的方法调用是异步的:
void Bar1()
{
var result = await Foo1Async();
// ...
}
void Bar2()
{
var result = await Foo2Async();
// ...
}
我想我需要使用Task.ContinueWith
,并提出了这个问题:
readonly object syncLock = new Object();
private Task currentOperationTask = TaskUtilities.CompletedTask;
public Task<TResult> EnqueueOperation<TResult>(Func<Task<TResult>> continuationFunction)
{
lock (this.syncLock)
{
var operation = this.currentOperationTask.ContinueWith(predecessor => continuationFunction()).Unwrap();
this.currentOperationTask = operation;
return operation;
}
}
我这样使用它:
void Bar1()
{
var result = await EnqueueOperation(() => Foo1Async());
// ...
}
void Bar2()
{
var result = await EnqueueOperation(() => Foo2Async());
// ...
}
这是解决此问题的正确方法吗?我应该注意哪些陷阱?
答案 0 :(得分:1)
您的代码可以正常运行,我认为这是解决问题的合理方法。
更简单的方法是使用AsyncLock
from Nito AsyncEx:
private readonly AsyncLock asyncLock = new AsyncLock();
public async Task<TResult> EnqueueOperation<TResult>(
Func<Task<TResult>> continuationFunction)
{
using (await asyncLock.LockAsync())
{
return await continuationFunction();
}
}