通过Continuewith捕获多个Task回调
本文关键字:Task 回调 Continuewith 通过 | 更新日期: 2023-09-27 18:27:06
我想同时运行多个任务。每个任务都将返回一个值类型。
有人能告诉我如何通过ContinueWith
捕捉所有的回调吗?
我的测试代码:
static async Task<List<string>> ListAsync()
{
await Task.Delay(1000);
return new List<string>() { "Item 1", "Item 2" };
}
static async Task<int> IntAsync()
{
await Task.Delay(1000);
return 10;
}
static async Task<string> StringAsync()
{
await Task.Delay(1000);
return "My string";
}
static async Task Test()
{
Task t1 = StringAsync();
Task t2 = IntAsync();
Task t3 = ListAsync();
await Task.WhenAny(t1, t2, t3).ContinueWith(t =>
{
//how can I catch callbacks here?
});
}
如果您试图检索所有任务的结果,一旦它们全部完成,您可以简单地使用Task.WhenAll
。如果所有任务都返回相同的结果,则Task.WhenAll(Task[]重载将返回一个Task。在这种情况下,await Task.WhenAll
将返回带有任务结果的数组,顺序为:
var t1=Task.Run(()=>{...;return 1});
var t2=Task.Run(()=>{...;return 2});
var t3=Task.Run(()=>{...;return 3});
int[] results=await Task.WhenAll(t1,t2,t3);
//Check t1's result
Debug.Assert(results[0]==1);
当任务返回不同的结果时,会调用Task.WhenAll(params Task[]),它只返回一个Task。不过,您仍然可以使用其Result
属性访问每个任务的结果,而不会有任何阻塞风险:
var t1=Task.Run(()=>{...;return 1});
var t2=Task.Run(()=>{...;return "Hi"});
var t3=Task.Run(()=>{...;return new[]{1,2,3}});
await Task.WhenAll();
Debug.Assert(t2.Result=="Hi");
在使用await
时,没有理由使用ContinueWith
,因为等待与使用ContinueWith
大致相同-它不启动任何异步执行,它在等待时不会阻止已经运行的任务完成,它提取结果并将同步上下文设置为等待启动前的状态。
如果不想调用具有不同延续的任务,则需要为每个任务指定延续:
static async Task Test()
{
Task t1 = StringAsync().ContinueWith(t => System.Console.Out.WriteLine("string"));
Task t2 = IntAsync().ContinueWith(t => System.Console.Out.WriteLine("int"));
Task t3 = ListAsync().ContinueWith(t => System.Console.Out.WriteLine("list"));
await Task.WhenAny(t1, t2, t3);
// use WhenAll if you want to wait until all tasks are done
}
WhenAny
将在任何子任务完成时完成,然后触发continuation,因此continuation将只调用一次。
如果你想在所有任务完成后调用回调一次,最简单的方法是:
static async Task Test()
{
Task t1 = StringAsync();
Task t2 = IntAsync();
Task t3 = ListAsync();
await Task.WhenAll(t1, t2, t3);
// your continuation logic here
}