如何正确使用 Task.WhenAll() [英] How to use Task.WhenAll() correctly

查看:19
本文介绍了如何正确使用 Task.WhenAll()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 Task.WhenAll 来等待多个任务的完成.

I am trying to use Task.WhenAll to await completion of multiple tasks.

我的代码如下 - 它应该启动多个异步任务,每个任务检索一条总线路线,然后将它们添加到本地数组.但是,Task.WhenAll(...) 立即返回,本地路由数组的计数为零.这看起来很奇怪,因为我希望每个 Task 中的各种 await 语句意味着流程被暂停,并且 Task 不会返回直到完成.

My code is below - it is supposed to launch multiple async tasks, each of which retrieves a bus route and then adds them to a local array. However, Task.WhenAll(...) returns immediately, and the count of the local routes array is zero. This seems strange, since I would expect the various await statements within each Task to mean that the flow is suspended, and the Task does not return until it's finished.

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

我显然做错了什么 - 但什么?

I'm obviously doing something wrong - but what?

推荐答案

这归结为对 async-await 的真正工作原理缺乏基本的了解.

This was down to a basic lack of understanding of how async-await really works.

内部任务将流程返回到外部任务,然后在等待返回之前完成.

The inner task was returning flow to the outer task, which then finished before the await ever returned.

为了实现我想要的,我需要进行如下重构:

To achieve what I wanted, I needed to refactor as follows:

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
}

感谢 戴夫犯规

这篇关于如何正确使用 Task.WhenAll()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆