I am trying to use Task.WhenAll to await completion of multiple tasks.  
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?
Task. WhenAll creates a task that will complete when all of the supplied tasks have been completed. It's pretty straightforward what this method does, it simply receives a list of Tasks and returns a Task when all of the received Tasks completes.
WhenAll only aggregates the tasks; it does not start them for you.
The call to WhenAll<TResult>(Task<TResult>[]) method does not block the calling thread. However, a call to the returned Result property does block the calling thread.
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
}
Thanks to Dave Smits
I suspect the problem is your call to Task.Factory.StartNew(). I suspect you're ending up with a Task<Task>, and you're only finding out when it's effectively started the task.
Try this instead:
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);
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With