我有3个任务:
private async Task<Cat> FeedCat() {}
private async Task<House> SellHouse() {}
private async Task<Tesla> BuyCar() {}
它们都需要在我的代码继续之前运行,我也需要每个结果。这些结果之间没有任何共同之处
我如何调用和等待3个任务完成,然后得到结果?
我有3个任务:
private async Task<Cat> FeedCat() {}
private async Task<House> SellHouse() {}
private async Task<Tesla> BuyCar() {}
它们都需要在我的代码继续之前运行,我也需要每个结果。这些结果之间没有任何共同之处
我如何调用和等待3个任务完成,然后得到结果?
当前回答
只需要分别等待这三个任务,在启动它们之后:
var catTask = FeedCat();
var houseTask = SellHouse();
var carTask = BuyCar();
var cat = await catTask;
var house = await houseTask;
var car = await carTask;
注意:如果任何一个任务抛出异常,这段代码可能会在后面的任务完成之前返回异常,但它们都将运行。在几乎所有的情况下,当你已经知道结果是理想的时候就不要等待。在边缘情况下,可能不是这样。
其他回答
只需要分别等待这三个任务,在启动它们之后:
var catTask = FeedCat();
var houseTask = SellHouse();
var carTask = BuyCar();
var cat = await catTask;
var house = await houseTask;
var car = await carTask;
注意:如果任何一个任务抛出异常,这段代码可能会在后面的任务完成之前返回异常,但它们都将运行。在几乎所有的情况下,当你已经知道结果是理想的时候就不要等待。在边缘情况下,可能不是这样。
使用任务。然后等待结果:
var tCat = FeedCat();
var tHouse = SellHouse();
var tCar = BuyCar();
await Task.WhenAll(tCat, tHouse, tCar);
Cat cat = await tCat;
House house = await tHouse;
Tesla car = await tCar;
//as they have all definitely finished, you could also use Task.Value.
如果你正在使用c# 7,你可以使用一个方便的包装方法,像这样…
public static class TaskEx
{
public static async Task<(T1, T2)> WhenAll<T1, T2>(Task<T1> task1, Task<T2> task2)
{
return (await task1, await task2);
}
}
...当您希望等待多个具有不同返回类型的任务时,可以启用这样的方便语法。当然,您必须对等待的不同数量的任务进行多次重载。
var (someInt, someString) = await TaskEx.WhenAll(GetIntAsync(), GetStringAsync());
但是,如果您打算把这个例子变成现实,请参阅Marc Gravell对ValueTask和已经完成的任务的一些优化的回答。
var dn = await Task.WhenAll<dynamic>(FeedCat(),SellHouse(),BuyCar());
如果你想访问Cat,你可以这样做:
var ct = (Cat)dn[0];
这是非常简单的做法和非常有用的使用,没有必要去追求一个复杂的解决方案。
await语句不是使代码按顺序运行吗?考虑以下代码
class Program
{
static Stopwatch _stopwatch = new();
static async Task Main(string[] args)
{
Console.WriteLine($"fire hot");
_stopwatch.Start();
var carTask = BuyCar();
var catTask = FeedCat();
var houseTask = SellHouse();
await carTask;
await catTask;
await houseTask;
Console.WriteLine($"{_stopwatch.ElapsedMilliseconds} done!");
Console.WriteLine($"using await");
_stopwatch.Restart();
await BuyCar();
await FeedCat();
await SellHouse();
Console.WriteLine($"{_stopwatch.ElapsedMilliseconds} done!");
}
static async Task BuyCar()
{
Console.WriteLine($"{_stopwatch.ElapsedMilliseconds} buy car started");
await Task.Delay(2000);
Console.WriteLine($"{_stopwatch.ElapsedMilliseconds} buy car done");
}
static async Task FeedCat()
{
Console.WriteLine($"{_stopwatch.ElapsedMilliseconds} feed cat started");
await Task.Delay(1000);
Console.WriteLine($"{_stopwatch.ElapsedMilliseconds} feed cat done");
}
static async Task SellHouse()
{
Console.WriteLine($"{_stopwatch.ElapsedMilliseconds} sell house started");
await Task.Delay(10);
Console.WriteLine($"{_stopwatch.ElapsedMilliseconds} sell house done");
}
}
fire hot
0 buy car started
3 feed cat started
4 sell house started
18 sell house done
1004 feed cat done
2013 buy car done
2014 done!
using await
0 buy car started
2012 buy car done
2012 feed cat started
3018 feed cat done
3018 sell house started
3033 sell house done
3034 done!