如何使用 Task.WhenAll [duplicate] 运行返回不同数据类型的任务列表

How to run list of Tasks that return different data types by using Task.WhenAll [duplicate]

提问人:Emil Abbas 提问时间:9/14/2023 最后编辑:Peter CsalaEmil Abbas 更新时间:9/14/2023 访问量:145

问:

因此,我有两个返回不同数据类型的方法。我想同时运行它们。并从他们俩那里得到结果。

public async Task<int> Ta1()
{
   await Task.Delay(100);
   return 100;
}

public async Task<string> Ta2()
{
   await Task.Delay(200);
   return "hello";
}

和 main 函数,其中创建任务列表并通过 Task.WhenAll 调用它

var tasks = new List<Task>();
tasks.Add(Ta1());
tasks.Add(Ta2());

await Task.WhenAll(tasks);
            
var a1= //get value from Ta1;
var a2 = //get value from Ta2;
C# 异步 任务 task-parallel-library

评论

1赞 Panagiotis Kanavos 9/14/2023
任务已经开始。 等待已经执行的任务,它不会启动它们。不过,这些任务现在唯一要做的就是睡觉。在 WhenAll 之后,您可以检查每个任务的值Task.WhenAllResult
0赞 Panagiotis Kanavos 9/14/2023
您想要解决的实际问题是什么?A 不是一个线程,它是一个承诺,即某件事会完成,并可能在未来产生结果。返回的任务由在间隔后触发的计时器触发。返回的任务实际上表示由线程池线程执行的委托(尽管即使这样也可以更改)TaskTask.DelayTask.Run
1赞 Emil Abbas 9/14/2023
我可以做这样的事情,但不知道这是一个很好的做法 var a = (Task<int>)tasks[0];var b = (任务<字符串>)任务[0];
0赞 Good Night Nerd Pride 9/14/2023
这在实践中不会很好,但我认为这是唯一的方法。你为什么要这样做?

答:

4赞 ClemB 9/14/2023 #1

你可以像这样做


var tasks = new List<Task>();
var ta1 = Ta1();
var ta2 = Ta2();
tasks.Add(ta1);
tasks.Add(ta2);

await Task.WhenAll(tasks);

var a1 = ta1.Result;//get value from Tel1;
var a2 = ta2.Result;//get value from Tel2;

评论

1赞 Enigmativity 9/14/2023
我宁愿这样做,因为您可以更轻松地重构。规则是每当你在方法中时使用。await ta1ta1.Resultawaitasync
0赞 Peter Csala 9/14/2023 #2

您可以创建以下帮助程序方法,使用法更加简化

public static async Task<(T1, T2)> WhenAllCompleted<T1, T2>(Task<T1> t1, Task<T2> t2)
{
  await Task.WhenAll(t1, t2);
  return (await t1, await t2);
}

用法

var (a1, a2) = await WhenAllCompleted(Ta1(), Ta2());

评论

0赞 Enigmativity 9/14/2023
当您在下一行执行时,这是多余的。你不妨把它做成一个扩展方法,写成这样: .然后你可以做.await Task.WhenAll(t1, t2);return (await t1, await t2);public static async Task<(T1, T2)> AndWhen<T1, T2>(this Task<T1> t1, Task<T2> t2) => (await t1, await t2);var (a1, a2) = await Ta1().AndWhen(Ta2());
0赞 Enigmativity 9/14/2023
在它完成之前的回报听起来确实有点误导。Task<(T1, T2)>WhenAllCompleted
1赞 Panagiotis Kanavos 9/14/2023
just 的 fault 和 cancellation 行为不等同于 。我会用而不是return (await t1, await t2)await Task.WhenAll().Resultawait
1赞 Theodor Zoulias 9/14/2023
@Enigmativity是必需的。它不是多余的,因为在这个问题中彻底讨论了原因:等待具有不同结果的多个任务await Task.WhenAll
2赞 Theodor Zoulias 9/15/2023
@Enigmativity是的。用于等待这两项任务,以防其中一项任务失败。如果没有,一项任务就有可能成为即发即弃,以防另一项任务失败。await Task.WhenAll