2012-01-01 35 views
0

私は、.NET Frameworkで並列プログラミングのサンプルをhereに配置し、本当に素晴らしいことを学びました。Task.Factory.ContinueWhenAllのタスク配列にタスクを動的に割り当てる

具体的には、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に渡される前に実行されていることも確認できます。

私は、これらのそれぞれをTask.Factory.ContinueWhenAllに渡すために、foreachループではなくラムダ式を使用する必要があると考えています。残念ながら、ラムダ式を使用してタスクのURLがどのように適用されているかを調べるのは苦労しています。

私がやろうとしていることが可能なのかどうか分からないので、提案や指摘、助けがあれば大歓迎です。 DownLoad(url)を使用してタスクオブジェクトを作成しているため、

+0

でコードを確認することができ、どのように質問を閉じたり、それに答えて、それを閉じてはどうですか? – Noctis

答えて

0

です。 DownLoad(url)方法では、タスクが実際にすでに開始されていたあなたはこれを解決するために、あなたはParallelExtensionsExtras /拡張/ 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

お返事ありがとうございます。投稿後に指摘した問題を認識しました。私はこれを行うことで問題を解決しました。 'List > tasks = new List (); foreach(URLの文字列URL) { タスクタスク=ダウンロード(URL); tasks.Add(タスク); } Task.Factory.ContinueWhenAll(tasks.ToArray()、ConcurrentTasksCompleted); ' – rise4peace

関連する問題