我一直在使用位于here的.NET Framework并行编程示例,并学习一些非常棒的东西。
具体来说,我正在尝试构建一个简单的程序,该程序会引入一个rss源列表,然后解析出特定的信息。
在解决方案 AsyncDownload_CSharp 中,它提供了许多如何异步下载的示例。我对以下代码有了相当不错的理解:
// Concurrent async requests
Task.Factory.ContinueWhenAll(new []
{
Download("http://blogs.msdn.com/pfxteam"),
Download("http://blogs.msdn.com/nativeconcurrency"),
Download("http://exampleexampleexample.com"), // will fail
Download("http://msdn.com/concurrency"),
Download("http://bing.com")
}, ConcurrentTasksCompleted).Wait();
上面的代码有任务硬编码列表,我一直试图弄清楚如何动态生成任务列表,我在运行时通过foreach循环或其他一些方式分配url的值重复循环。
我想出的代码是动态构建任务列表并将其传递给Task.Factory.ContinueWhenAll看起来像这样:
private void btnFeeds_Click(object sender, EventArgs e)
{
string[] urls = new[] { "http://blogs.msdn.com/pfxteam", "http://msdn.com/concurrency", "http://bing.com" };
List<Task<string>> tasks = new List<Task<string>>();
foreach (string url in urls)
{
tasks.Add(Download(url));
}
Task.Factory.ContinueWhenAll(tasks, ConcurrentTasksCompleted).Wait();
}
不幸的是,当我单步执行调试器时,我不仅看到正在构建的任务列表,而且因为它们被添加到任务列表中,但我也看到它们在传递给Task.Factory.ContinueWhenAll之前被执行。
我认为我需要使用Lambda表达式而不是foreach循环将每个表达式传递给Task.Factory.ContinueWhenAll。不幸的是,我很难弄清楚如何使用Lambda表达式应用任务的URL。
我不确定我尝试做的事情是否可行,所以任何建议,指示或帮助都会受到高度赞赏。
答案 0 :(得分:0)
因为您正在使用方法DownLoad(url)
来创建任务对象。在DownLoad(url)
方法中,任务实际上已经启动,您可以在ParallelExtensionsExtras / Extensions / EAP / WebClientExtensions.cs中检查代码
/// <summary>Downloads the resource with the specified URI as a byte array, asynchronously.</summary>
/// <param name="webClient">The WebClient.</param>
/// <param name="address">The URI from which to download data.</param>
/// <returns>A Task that contains the downloaded data.</returns>
public static Task<byte[]> DownloadDataTask(this WebClient webClient, string address)
{
return DownloadDataTask(webClient, new Uri(address));
}
/// <summary>Downloads the resource with the specified URI as a byte array, asynchronously.</summary>
/// <param name="webClient">The WebClient.</param>
/// <param name="address">The URI from which to download data.</param>
/// <returns>A Task that contains the downloaded data.</returns>
public static Task<byte[]> DownloadDataTask(this WebClient webClient, Uri address)
{
// Create the task to be returned
var tcs = new TaskCompletionSource<byte[]>(address);
// Setup the callback event handler
DownloadDataCompletedEventHandler handler = null;
handler = (sender, e) => EAPCommon.HandleCompletion(tcs, e, () => e.Result, () => webClient.DownloadDataCompleted -= handler);
webClient.DownloadDataCompleted += handler;
// Start the async work
try
{
webClient.DownloadDataAsync(address, tcs);
}
catch(Exception exc)
{
// If something goes wrong kicking off the async work,
// unregister the callback and cancel the created task
webClient.DownloadDataCompleted -= handler;
tcs.TrySetException(exc);
}
// Return the task that represents the async operation
return tcs.Task;
}