动态地将任务分配给Task数组以供Task. factory . continuewhenall进行处理

本文关键字:Task factory continuewhenall 处理 数组 任务分配 动态 | 更新日期: 2023-09-27 18:19:13

我一直在玩。net框架并行编程示例,并学习了一堆真正伟大的东西。

具体来说,我正在尝试构建一个简单的程序,它可以拉入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 looks,像这样:

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。

我不确定我正在尝试做的事情是否可能,所以任何建议,指针或帮助都将非常感谢。

动态地将任务分配给Task数组以供Task. factory . continuewhenall进行处理

因为您正在使用方法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; 
    }