9

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

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

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

私は明らかに何か間違ったことをしていますが、何ですか?

4

2 に答える 2

8

これは、async-await が実際にどのように機能するかについての基本的な理解の欠如に起因していました。

内側のタスクはフローを外側のタスクに戻していましたが、それは await が戻る前に終了しました。

私が望んでいたことを達成するには、次のようにリファクタリングする必要がありました。

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
}

デイブ・スミッツに感謝

于 2012-08-14T11:01:52.290 に答える
6

への呼び出しに問題があると思われます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);
于 2012-08-14T11:00:26.150 に答える