启动异步操作,然后等待
本文关键字:等待 然后 异步操作 启动 | 更新日期: 2023-09-27 18:32:12
我现在才开始玩异步和等待。 我有 8 个单独的数据库调用,其中一些依赖于其他调用。 我希望能够启动 3 个异步方法,然后当某个 1 返回时,启动其他 3 个,然后当某个 1 从中返回时,再启动 2 个。 我目前正在使用 3 个 Parallel.Invoke 方法来完成此操作,但每个并行都必须等到所有方法返回。 我只关心 1 个方法返回,其他方法可以在后台运行,直到最后await Task.WhenAll(t1,t2,t3,...,t6)
。 有没有办法用异步/等待来做到这一点?
我知道 await 不是阻塞,但它会停止执行我的主方法(带有 8 db 调用),直到值从该方法返回(就像同步方法一样)。
您可以使用
Task.WhenAny
来等待以下几个任务中的任何一个:
var completedTask = await Task.WhenAny(t1, t2, t3, ...);
如果你有一个更复杂的依赖结构,那么我建议用async
方法表示它:
static async Task DoMasterOperationAsync()
{
var result = await StartSomething();
await Task.WhenAll(DoComplexOperationAsync(), result.NextT1Async());
}
static async Task DoComplexOperationAsync()
{
var result1 = await T1Async();
await Task.WhenAll(result1.NextT1Async(), result1.NextT2Async(), result1.NextT3Async());
}
await Task.WhenAll(DoMasterOperationAsync(), t2, t3, ...);
我的问题是我不知道Task.Run
可以让你开始一个任务,然后等待它。 我在@StephenCleary的另一个答案中找到了这一点。 谢谢斯蒂芬,你在那里得到了我的赞成票! 这是我完全人为的例子,它完成了我上面设定的任务:
Func<Task<int>> t1 = async () => { await Task.Delay(4000); return 1; };
Func<Task<int>> t2 = async () => { await Task.Delay(5000); return 2; };
Func<int, Task<int>> t3 = async (val) => { await Task.Delay(3000); return 3; };
Func<int, Task<int>> t4 = async (val) => { await Task.Delay(4000); return 4; };
Func<int, Task<int>> t5 = async (val) => { await Task.Delay(3000); return 5; };
Func<int, Task<int>> t6 = async (val) => { await Task.Delay(2000); return 6; };
Func<int, Task<int>> tSecondary = async (val) => { await Task.Delay(3000); return 7; };
Func<Task<int>> tPrimary = async () => { await Task.Delay(2000); return 8; };
//kick off first 3 calls
var primaryR = Task.Run(tPrimary);
var t1R = Task.Run(t1);
var t2R = Task.Run(t2);
//await 1 of the 3
var primary = await primaryR;
//start 2 of 3 dependent tasks
var t3R = Task.Run(() => t3(primary));
var t4R = Task.Run(() => t4(primary));
//kick off and await secondaryMasterTaskAsync
var secondary = await tSecondary(primary);
//start final 2
var t5R = Task.Run(() => t5(secondary));
var t6R = Task.Run(() => t6(secondary));
//await all tasks that haven't been awaited previously
var tasks = await Task.WhenAll(t1R, t2R, t3R, t4R, t5R, t6R);