C# Task.When任何节流效率

C# Task.When任何节流效率,c#,asynchronous,async-await,task-parallel-library,C#,Asynchronous,Async Await,Task Parallel Library,我最近阅读了一些关于使用TAP的文档,特别是在较小的标题“Task.WhenAny”下。它们说明了任务的4个主要目的。WhenAny: 冗余 交错 节流 早期救助 在交错(以及间接的节流)小节下面,他们有以下代码 List<Task<Bitmap>> imageTasks = (from imageUrl in urls select GetBitmapAsync(imageUrl)).ToList(); while(imageTasks.Count > 0)

我最近阅读了一些关于使用TAP的文档,特别是在较小的标题“Task.WhenAny”下。它们说明了任务的4个主要目的。WhenAny:

  • 冗余
  • 交错
  • 节流
  • 早期救助
在交错(以及间接的节流)小节下面,他们有以下代码

List<Task<Bitmap>> imageTasks = 
(from imageUrl in urls select GetBitmapAsync(imageUrl)).ToList();
while(imageTasks.Count > 0)
{
    try
    {
        Task<Bitmap> imageTask = await Task.WhenAny(imageTasks);
        imageTasks.Remove(imageTask);

        Bitmap image = await imageTask;
        panel.AddImage(image);
    }
    catch{}
}
列出图像任务=
(从URL中的imageUrl选择GetBitmapAsync(imageUrl)).ToList();
而(imageTasks.Count>0)
{
尝试
{
Task imageTask=等待任务。WhenAny(imageTasks);
imageTasks.Remove(imageTask);
位图图像=等待图像任务;
面板。添加图像(图像);
}
捕获{}
}

这段代码不是很低效吗?我假设一次任务。当所有的第一个任务完成时,它会将列表中的其他任务设置为“RanToCompletion”或“Cancelled”或其他一些状态,这些状态会扼杀其他任务的进度。因此,即使列表中只有两个任务要下载图像,如本例中所示,一个图像是2MB,另一个是4MB,2MB图像很可能会首先完成(并且会收到2ish MB或另一个)。然后,它将从列表中删除2MB并重新开始循环。这似乎会再次启动4MB下载,基本上浪费了已经取得的进展,对吗?

所有图像下载都会在调用“GetBitmapAsync”的瞬间并行执行

循环只检查完成了哪些操作并将它们添加到面板中。这样一来,您可以在图像到达后立即看到它们


任务结束后,它不会影响其他任务的状态。

为什么不编写代码来测试您的假设?我通常会这样做,以了解某些概念的详细信息。…
当任何
将产生集合中提供的某个已完成任务的结果时,它不会将所有任务设置为已取消或已完成。一旦执行图像操作,它将重复循环并获得下一个要添加的图像<另一方面,code>whalll将返回一个仅在指定任务完成时才会完成的任务。您始终可以使用TPL数据流,它包括节流等功能。此外,TPL的管道功能可以更好地满足上述代码试图实现的目的,这是因为任务不会重新运行,因为任务只有在处于创建状态时才会运行。当它处于任何其他状态时,它都不会运行,但会返回它的当前状态,对吗?虽然您可以创建任务,但大多数情况下,任务代表的是已经在运行的、正在执行的任务,因此一旦完成,您就无法使用该任务再次执行它,您需要创建表示同一操作的另一次执行的其他。