我正在从微软文档中学习异步编程, 我不明白以下使用 WhenAny 方法的示例:
var breakfastTasks = new List<Task> { eggsTask, baconTask, toastTask };
while (breakfastTasks.Count > 0)
{
Task finishedTask = await Task.WhenAny(breakfastTasks);
if (finishedTask == eggsTask)
{
Console.WriteLine("Eggs are ready");
}
else if (finishedTask == baconTask)
{
Console.WriteLine("Bacon is ready");
}
else if (finishedTask == toastTask)
{
Console.WriteLine("Toast is ready");
}
await finishedTask;
breakfastTasks.Remove(finishedTask);
}
您可以在这里找到它。
这段代码的问题在于,eggsTask 引用了一个Task<Egg>
对象,baconTask 引用了一个
Task<Bacon>
对象,toastTask 引用了一个
Task<Toast>
对象。然后他将这 3 个变量放入一个列表中,然后该列表成为
Task.WhenAny(breakfastTasks)
方法中的参数。现在,我相信使用了 WhenAny 的非泛型重载,您可以在
here看到它。具体来说,我相信使用了此重载:public static System.Threading.Tasks.Task<System.Threading.Tasks.Task> WhenAny(System.Collections.Generic.IEnumerable<System.Threading.Tasks.Task> tasks);
IEnumerable<Task>
。此重载还会返回一个
Task<Task>
对象,完成后将成为
Task
对象。因此,在这个方法中,您放入
Task
对象,当一个对象完成时,该方法返回一个
Task
对象,它是第一个完成的
Task
对象。但是,当
Task<Egg>
对象完成时,它就变成了
Egg
对象, 当
Task<Bacon>
对象完成时,它会成为
Bacon
对象,而当
Task<Toast>
对象完成时,它会成为
Toast
对象。所以,下面这行似乎不正确:
Task finishedTask = await Task.WhenAny(breakfastTasks);
Egg
对象,该对象应该由该方法返回,但该方法完成后仅返回一个
Task
对象。您能解释一下吗?
的重载的返回类型为
Task<Task>
。与 await
关键字结合使用,您将获得从给定的要观察的任务列表中完成的 Task
参考。此返回的 Task
引用正在引用您现有的任务引用之一
eggsTask
(Task<Egg>
)、baconTask
(Task<Bacon>
) 或 toastTask
(Task<Toast>
)。它不会返回任何 Egg
、Bacon
或 Toast
引用。要从已完成的任务中获取结果,您仍然需要在 await
实例上调用 Task<...>
。作为一个例子,你可以写if (finishedTask == eggsTask)
{
Console.WriteLine("Eggs are ready");
Egg egg = await eggsTask;
}
从已完成的任务中获取
Egg
参考。由于任务已经完成,这个
await
调用将立即返回 Egg
引用(并将其保存在 egg
变量中)。