排队等待异步代码按顺序执行

本文关键字:顺序 执行 代码 等待 异步 排队 | 更新日期: 2023-09-27 18:21:36

在任何时候,我都可以收到一个需要长时间运行的操作才能满足的方法调用。

这些方法有几种。因为它们共享一个资源,所以重要的是它们不能并发运行——每个都应该按顺序运行。

通常,我只会按顺序打电话:

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());
    // ...
}

这是解决这个问题的正确方法吗?有什么陷阱我应该注意吗?

排队等待异步代码按顺序执行

您的代码会很好地工作,我认为这是解决问题的合理方法。

一种更简单的方法是使用Nito AsyncEx:中的AsyncLock

private readonly AsyncLock asyncLock = new AsyncLock();
public async Task<TResult> EnqueueOperation<TResult>(
    Func<Task<TResult>> continuationFunction)
{
    using (await asyncLock.LockAsync())
    {
        return await continuationFunction();
    }
}