C#异步编程中使用WhenAny

问题描述 投票:0回答:1

我正在从微软文档中学习异步编程, 我不明白以下使用 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);


假设 EggTask 首先完成,它会给出一个

Egg

 对象,该对象应该由该方法返回,但该方法完成后仅返回一个 
Task
 对象。

您能解释一下吗?

c# asynchronous
1个回答
0
投票

Task.WhenAny()

 的重载的返回类型为 
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
变量中)。
    

© www.soinside.com 2019 - 2024. All rights reserved.