动态地将任务分配给Task数组以供Task.Factory.ContinueWhenAll处理

发布于 2024-12-24 02:00:58 字数 1602 浏览 4 评论 0原文

我一直在使用位于 这里,学习了很多很棒的东西。

具体来说,我正在尝试构建一个简单的程序,该程序提取 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。

我不确定我想做的事情是否可行,因此任何建议、指示或帮助将不胜感激。

I've been playing around with the Samples for Parallel Programming with the .NET Framework located here, and learning a bunch of really great things.

Specifically I'm trying to build a simple program that pulls in a list of rss feeds and then parses out specific information.

In the solution, AsyncDownload_CSharp, it provides a number of examples of how to download asynchronously. I've got a pretty decent understanding of the following piece of code:

// 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();

The code above has the list of Tasks hard code and I've been trying to figure out how would I go about generating that list of Tasks dynamically where I assign the value of url at runtime either through a foreach loop or some other repeat loop.

The code I came up with to build the list of Tasks dynamically and pass it to the Task.Factory.ContinueWhenAll looks like this:

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();

}

Unfortunately, when I step through the debugger not only do I see the Tasks list being built but as they're being added to the tasks list but I also see them being executed before being passed to the Task.Factory.ContinueWhenAll.

I'm thinking I need to use a lambda expression, instead of that foreach loop, to pass each of these to the Task.Factory.ContinueWhenAll. Unfortunately, I'm having a hard time figuring out how the url for the task is applied using the lambda expression.

I'm not sure if what I'm trying to do is even possible, so any suggestions, pointers, or help would be greatly appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

埋葬我深情 2024-12-31 02:00:58

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

because you are using method DownLoad(url) to create a task object. in the DownLoad(url) method, the task actually had already been started, you can check code in 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; 
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文