2012-08-14 12 views
6

複数のタスクの完了を待つためにTask.WhenAllを使用しようとしています。Task.WhenAll()を正しく使用する方法

私のコードは以下の通りです。複数の非同期タスクを起動することになっています。それぞれのタスクは、バスルートを取得してローカルアレイに追加します。ただし、Task.WhenAll(...)はすぐに戻り、ローカルルート配列の数はゼロです。これは、各タスク内のさまざまな「待機」ステートメントがフローが中断され、タスクが終了するまで戻らないことを意味することを期待しているので、奇妙に思えます。

 List<Task> monitoredTasks = new List<Task>(); 
     foreach (BusRouteIdentifier bri in stop.services) 
     { 
      BusRouteRequest req = new BusRouteRequest(bri.id); 

      // Start a new task to fetch the route for each stop 
      Task getRouteTask = Task.Factory.StartNew(async() => 
      { 
       var route = await BusDataProviderManager.DataProvider.DataBroker.getRoute(req); 

        // Add the route to our array (on UI thread as it's observed) 
        await dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, delegate 
        { 
         this.routes.Add(route); 
        }); 
      }); 

      // Store the task in our monitoring list 
      monitoredTasks .Add(getRouteTask); 
     } 

     Debug.WriteLine("Awaiting WHENALL"); 
     await Task.WhenAll(monitoredTasks); 
     Debug.WriteLine(string.Format("WHENALL returned (routes count is {0} ", this.routes.Count)); 

     this.OnWillEndFetchingRoutes(new EventArgs()); 

私は明らかに何か間違っていますが、何ですか?

+0

あなたは最終的には 'Task'が故障状態になっていないかどうかを確認しようとしました

 List<Task<BusRoute>> routeRetrievalTasks = new List<Task<BusRoute>>(); foreach (BusRouteIdentifier bri in stop.services) { BusRouteRequest req = new BusRouteRequest(bri.id); routeRetrievalTasks.Add(BusDataProviderManager.DataProvider.DataBroker.getRoute(req)); } foreach (var task in routeRetrievalTasks) { var route = await task; this.routes.Add(route); // triggers events } 

感謝を:

私が欲しかったものを達成するために、私は次のようにリファクタリングするために必要な? –

+0

私はそれがforeachループの中で何か間違った 'dispatcher'を待つかもしれないと思う。 UIスレッドはすぐに観察され、表示されますか? –

+0

@ie。はい、その状態はRanToCompletionです。配列内のすべてのタスクの状態は、RanToCompletionでもありますが、実際に個別に検査すると、それぞれの結果フィールドはWaitingForActivationになります –

答えて

6

は、これはどのように実際に動作する非同期待つの理解の基本的な不足のためにダウンしていました。

内部タスクが外部タスクにフローを戻していましたが、外部タスクはそれまでに待っていた前に終了しました。 Dave Smits

5

Task.Factory.StartNew()へのご連絡が問題と思われます。私はあなたがTask<Task>に終わっていると思うし、それが実際にが開始したときだけを見つけているのです。タスクを開始しました。

代わりにこれを試してみてください:

Func<Task> taskFunc = async() => 
{ 
    var route = await BusDataProviderManager.DataProvider.DataBroker.getRoute(req); 

    // Add the route to our array (on UI thread as it's observed) 
    await dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, delegate 
    { 
     this.routes.Add(route); 
    }); 

} 

Task getRouteTask = Task.Run(taskFunc); 
+0

ありがとうございます。残りのメソッドは以前と同じように続行する、つまりタスクをタスクの配列に追加し、次に配列のTask.WhenAll(...)を呼び出すと仮定します。どのような場合、このアプローチは私の答えのものとどのように比較されますか?利点はありますか? –

+0

@CarlosP:正直言って、どちらが良いアプローチであるかについてコメントするのに十分な文脈はありません。しかし、はい、あなたの方法の残りの部分は以前と同じように続くでしょう。 –

関連する問題