我刚刚开始探索 PTL 并有一个设计问题。
我的场景:我有一个 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;
}