gpt4 book ai didi

c# - 任务并行库 WaitAny 设计

转载 作者:太空宇宙 更新时间:2023-11-03 17:35:54 25 4
gpt4 key购买 nike

我刚刚开始探索 TPL 并有一个设计问题。

我的场景:我有一个 URL 列表,每个 URL 都引用一个图像。我希望并行下载每个图像。下载至少一个图像后,我想执行一种方法来对下载的图像执行某些操作。该方法不应并行化——它应该是串行的。

我认为以下方法可行,但我不确定这是否是正确的方法。因为我有单独的类来收集图像和对收集到的图像做“某事”,所以我最终传递了一系列任务,这似乎是错误的,因为它暴露了如何检索图像的内部工作原理。但我不知道解决办法。实际上,这两种方法都有更多功能,但这并不重要。只知道它们真的不应该被归为一个既能检索图像又能对图像进行处理的大型方法。

//From the Director class
Task<Image>[] downloadTasks = collector.RetrieveImages(listOfURLs);

for (int i = 0; i < listOfURLs.Count; i++)
{
//Wait for any of the remaining downloads to complete
int completedIndex = Task<Image>.WaitAny(downloadTasks);
Image completedImage = downloadTasks[completedIndex].Result;

//Now do something with the image (this "something" must happen serially)
//Uses the "Formatter" class to accomplish this let's say
}

///////////////////////////////////////////////////

//From the Collector class
public Task<Image>[] RetrieveImages(List<string> urls)
{
Task<Image>[] tasks = new Task<Image>[urls.Count];

int index = 0;
foreach (string url in urls)
{
string lambdaVar = url; //Required... Bleh
tasks[index] = Task<Image>.Factory.StartNew(() =>
{
using (WebClient client = new WebClient())
{
//TODO: Replace with live image locations
string fileName = String.Format("{0}.png", i);
client.DownloadFile(lambdaVar, Path.Combine(
Application.StartupPath, fileName));
}

return Image.FromFile(Path.Combine(Application.StartupPath, fileName));
},
TaskCreationOptions.LongRunning | TaskCreationOptions.AttachedToParent);

index++;
}

return tasks;
}

最佳答案

通常,当您不关心任何其他任务的结果时,您会使用 WaitAny 来等待一个任务。例如,如果您只关心恰好返回的第一张图片。

这个怎么样。

这会创建两个任务,一个加载图像并将它们添加到阻塞集合中。第二个任务等待收集并处理添加到队列中的任何图像。加载完所有图像后,第一个任务关闭队列,以便第二个任务可以关闭。

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Net;
using System.Threading.Tasks;

namespace ClassLibrary1
{
public class Class1
{
readonly string _path = Directory.GetCurrentDirectory();

public void Demo()
{
IList<string> listOfUrls = new List<string>();
listOfUrls.Add("http://i3.codeplex.com/Images/v16821/editicon.gif");
listOfUrls.Add("http://i3.codeplex.com/Images/v16821/favorite-star-on.gif");
listOfUrls.Add("http://i3.codeplex.com/Images/v16821/arrow_dsc_green.gif");
listOfUrls.Add("http://i3.codeplex.com/Images/v16821/editicon.gif");
listOfUrls.Add("http://i3.codeplex.com/Images/v16821/favorite-star-on.gif");
listOfUrls.Add("http://i3.codeplex.com/Images/v16821/arrow_dsc_green.gif");
listOfUrls.Add("http://i3.codeplex.com/Images/v16821/editicon.gif");
listOfUrls.Add("http://i3.codeplex.com/Images/v16821/favorite-star-on.gif");
listOfUrls.Add("http://i3.codeplex.com/Images/v16821/arrow_dsc_green.gif");

BlockingCollection<Image> images = new BlockingCollection<Image>();

Parallel.Invoke(
() => // Task 1: load the images
{
Parallel.For(0, listOfUrls.Count, (i) =>
{
Image img = RetrieveImages(listOfUrls[i], i);
img.Tag = i;
images.Add(img); // Add each image to the queue
});
images.CompleteAdding(); // Done with images.
},
() => // Task 2: Process images serially
{
foreach (var img in images.GetConsumingEnumerable())
{
string newPath = Path.Combine(_path, String.Format("{0}_rot.png", img.Tag));
Console.WriteLine("Rotating image {0}", img.Tag);
img.RotateFlip(RotateFlipType.RotateNoneFlipXY);

img.Save(newPath);
}
});
}

public Image RetrieveImages(string url, int i)
{
using (WebClient client = new WebClient())
{
string fileName = Path.Combine(_path, String.Format("{0}.png", i));
Console.WriteLine("Downloading {0}...", url);
client.DownloadFile(url, Path.Combine(_path, fileName));
Console.WriteLine("Saving {0} as {1}.", url, fileName);
return Image.FromFile(Path.Combine(_path, fileName));
}
}
}
}

警告:该代码没有任何错误检查或取消。已经很晚了,您需要做点什么吗? :)

这是管道模式的一个例子。它假设获取图像的速度非常慢,并且锁定在阻塞集合中的成本不会导致问题,因为与下载图像所花费的时间相比,它发生的频率相对较低。

我们的书...您可以在 http://parallelpatterns.codeplex.com/ 阅读更多关于并行编程模式和其他模式的信息。第 7 章介绍了管道,附带的示例展示了具有错误处理和取消功能的管道。

关于c# - 任务并行库 WaitAny 设计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3003656/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com