Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在完成任何一个异步调用后立即使用异步调用的结果(返回类型不同)?_C# - Fatal编程技术网

C# 在完成任何一个异步调用后立即使用异步调用的结果(返回类型不同)?

C# 在完成任何一个异步调用后立即使用异步调用的结果(返回类型不同)?,c#,C#,下面的代码启动T1Async(),T2Async(),T3Async(),T4Async(),并等待所有调用完成,然后使用这些调用的结果。但是,运行这些异步调用的时间可能很短,也可能很长 Task<int> T1Async() { }; Task<string> T2Async() { }; Task<ClassX> T3Async() { }; Task<ClassY> T4Async() { }; var t1 = T1Async(); va

下面的代码启动
T1Async()
T2Async()
T3Async()
T4Async()
,并等待所有调用完成,然后使用这些调用的结果。但是,运行这些异步调用的时间可能很短,也可能很长

Task<int> T1Async() { };
Task<string> T2Async() { };
Task<ClassX> T3Async() { };
Task<ClassY> T4Async() { };

var t1 = T1Async();
var t2 = T2Async();
var t3 = T3Async();
var t4 = T4Async();

var v1 = await t1;
var v2 = await t2;
var v3 = await t3;
var v4 = await t4;
// Or Task.WhenAll(new Task[] { t1, t2, t3, t4 });

UseV1(v1); // Want these calls be run asap
UseV2(v2);
UseV3(v3);
UseV4(v4);

UseAll(v1, v2, v3, v4); // Need all the result here
Task T1Async(){};
任务T2Async(){};
任务T3Async(){};
任务T4Async(){};
var t1=T1Async();
var t2=T2Async();
var t3=T3Async();
var t4=T4Async();
var v1=等待t1;
var v2=等待t2;
var v3=等待t3;
var v4=等待t4;
//或者Task.WhenAll(新任务[]{t1,t2,t3,t4});
使用v1(v1);//希望这些电话尽快接通吗
UseV2(v2);
UseV3(v3);
使用v4(v4);
使用所有(v1、v2、v3、v4);//这里需要所有的结果

如何在调用完成后立即使用结果并确保所有结果都已使用

因此,您希望并行执行
UseVX
任务,但等待所有结果(不同类型),以便将其传递给
UseAll
方法

使用
任务。运行

var t1=Task.Run(异步()=>{var x=await t1();UseV1(x);返回x;});
var t2=Task.Run(异步()=>{var x=await t2();使用v2(x);返回x;});
var t3=Task.Run(异步()=>{var x=await t3();UseV3(x);返回x;});
var t4=Task.Run(异步()=>{var x=await t4();UseV4(x);返回x;});
等待任务时(t1、t2、t3、t4);
全部使用(t1.结果,t2.结果,t3.结果,t4.结果);
使用
继续使用

var t1=t1().ContinueWith(x=>{UseV1(x.Result);返回x.Result;});
var t2=t2().ContinueWith(x=>{UseV2(x.Result);返回x.Result;});
var t3=t3().ContinueWith(x=>{UseV3(x.Result);返回x.Result;});
var t4=t4().ContinueWith(x=>{UseV4(x.Result);返回x.Result;});
等待任务时(t1、t2、t3、t4);
全部使用(t1.结果,t2.结果,t3.结果,t4.结果);

要同时运行异步代码,请使用
Task.whalll
。要在每个操作完成时执行方法,请引入新的
async
方法:

async Task T1AndUseV1Async(){var v1=await T1Async();UseV1(v1);返回v1;};
异步任务T2AndUseV2Async(){var v2=await T2Async();UseV2(v2);返回v2;};
异步任务T3AndUseV3Async(){var v3=await T3Async();UseV3(v3);返回v3;};
异步任务t4和usev4async(){var v4=await T4Async();UseV4(v4);返回v4;};
var t1=T1AndUseV1Async();
var t2=t2和usev2async();
var t3=t3和usev3async();
var t4=t4和usev4async();
等待任务时(t1、t2、t3、t4);
使用全部(等待t1、等待t2、等待t3、等待t4);
可测试案例:

async Task<int> T1() { return await Task.FromResult(1); }
async Task<string> T2() { return await Task.FromResult("T2"); }
async Task<char> T3() { await Task.Delay(2000); return await Task.FromResult('A'); }
async Task<string> T4() { return await Task.FromResult("T4"); }

var t1 = T1().ContinueWith(x => { Console.WriteLine($"Use T1: {x.Result}"); return x.Result; });
var t2 = T2().ContinueWith(x => { Console.WriteLine($"Use T2: {x.Result}"); return x.Result; });
var t3 = T3().ContinueWith(x => { Console.WriteLine($"Use T3: {x.Result}"); return x.Result; });
var t4 = T4().ContinueWith(x => { Console.WriteLine($"Use T4: {x.Result}"); return x.Result; });
await Task.WhenAll(t1, t2, t3, t4);
Console.WriteLine("Done");
async Task T1(){return wait Task.FromResult(1);}
异步任务T2(){return await Task.FromResult(“T2”);}
异步任务T3(){await Task.Delay(2000);返回await Task.FromResult('A');}
异步任务T4(){return await Task.FromResult(“T4”);}
var t1=t1().ContinueWith(x=>{Console.WriteLine($“Use t1:{x.Result}”);返回x.Result;});
var t2=t2().ContinueWith(x=>{Console.WriteLine($“Use t2:{x.Result}”);返回x.Result;});
var t3=t3().ContinueWith(x=>{Console.WriteLine($“Use t3:{x.Result}”);返回x.Result;});
var t4=t4().ContinueWith(x=>{Console.WriteLine($“Use t4:{x.Result}”);返回x.Result;});
等待任务时(t1、t2、t3、t4);
控制台。写入线(“完成”);

任务。whalll()
也将帮助您查看此线程。您能否澄清一下
的意思使用(…)只需要一次调用的结果
?这可能是使用
任务之间的区别。WhenAny
任务。WhenAll
并行处理结果安全吗?@ColinM,
Use()
只需要这些异步调用中的一个结果。如果要在每次完成后立即运行任务,为什么要异步运行?似乎您可以将后续操作附加到每个异步任务中,然后等待它们全部完成最后一个任务。奇怪的是,看到代码等待已经等待的任务。你有什么理由愿意在这里等待吗?@huysentruitw:是的;如果未来的维护人员决定了
等待任务。当所有的
都是不必要的(意见问题)并将其删除时,使用
等待
而不是
结果
将防止
聚合异常
包装。是的,但在这种情况下,维护人员的工作也是将
.Result
更改为
wait
。我同意并不是每个维护人员都知道这一点,但决定
任务的是谁。当不再需要所有的
时,至少应该是:)@huysentruitw:理论上,是的;实际上,绝对不是。另外,在现实世界的代码中,
任务.wheall
wait
并不总是如此接近。让我把问题转过来:在异步代码中使用
Task.Result
是很奇怪的。您为什么喜欢这里的
Result
?这里没有运行时影响。对于
wait
,生成的代码要长一点,但我认为这对于(稍微)更易于维护的代码来说是一个小代价。
async Task<int> T1() { return await Task.FromResult(1); }
async Task<string> T2() { return await Task.FromResult("T2"); }
async Task<char> T3() { await Task.Delay(2000); return await Task.FromResult('A'); }
async Task<string> T4() { return await Task.FromResult("T4"); }

var t1 = T1().ContinueWith(x => { Console.WriteLine($"Use T1: {x.Result}"); return x.Result; });
var t2 = T2().ContinueWith(x => { Console.WriteLine($"Use T2: {x.Result}"); return x.Result; });
var t3 = T3().ContinueWith(x => { Console.WriteLine($"Use T3: {x.Result}"); return x.Result; });
var t4 = T4().ContinueWith(x => { Console.WriteLine($"Use T4: {x.Result}"); return x.Result; });
await Task.WhenAll(t1, t2, t3, t4);
Console.WriteLine("Done");