Я играл с примерами для параллельного программирования с .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();

В приведенном выше коде есть список жесткого кода задач, и я пытался выяснить, как мне динамически генерировать этот список задач, где я присваиваю значение url во время выполнения либо через цикл foreach, либо через какой-либо другая повторяющаяся петля.

Код, который я придумал для динамического построения списка задач и передачи его в 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.

Я думаю, мне нужно использовать лямбда-выражение вместо этого цикла foreach, чтобы передать каждое из них в Task.Factory.ContinueWhenAll. К сожалению, мне трудно понять, как применяется URL-адрес задачи с использованием лямбда-выражения.

Я не уверен, возможно ли то, что я пытаюсь сделать, поэтому любые предложения, указатели или помощь будут очень признательны.

-1
rise4peace 1 Янв 2012 в 05:47

1 ответ

Потому что вы используете метод 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; 
    }
0
谢圣鑫 1 Янв 2012 в 10:38
Спасибо за ответ. Я понял проблему, на которую вы указали, после публикации. Я решил проблему, выполнив это List<Task<string>> tasks = new List<Task<string>>(); foreach (string url in urls) { Task<string> task = Download(url); tasks.Add(task); } Task.Factory.ContinueWhenAll(tasks.ToArray(), ConcurrentTasksCompleted);
 – 
rise4peace
2 Янв 2012 в 00:58