简体   繁体   中英

Await results of several different asynchronous operations using Task.WhenAny

I've been searching for a solution for a while now to what seems like it must be a simple problem. However, every example that I find creates a collection of Task s similar to this one (taken from the How to: Extend the Async Walkthrough by Using Task.WhenAll (C# and Visual Basic) page on MSDN):

IEnumerable<Task<int>> downloadTasksQuery = 
    from url in urlList select ProcessURLAsync(url);

I am unable to do this as I want to call different async methods and await the results... something more like this (but not this because this doesn't seem to do anything):

var getTicketTasks = new List<Task<IEnumerable<ITicket>>>();
getTicketTasks.Add(new Task(() => Model.GetTicketsAsync(eventDate)));
getTicketTasks.Add(new Task(() => Model.GetGuestTicketsAsync(eventDate)));
...
getTicketTasks.Add(new Task(() => Model.GetOtherTicketsAsync(eventDate)));

IEnumerable<ITicket>[] tickets = await Task.WhenAll(getTicketTasks);

So how can I call a number of async methods and await the results using the Task.WhenAll method?

Don't use that task constructor to call an asynchronous method*. Simply call these methods, store the returned tasks and await all of them together with Task.WhenAll :

var getTicketTasks = new List<Task<IEnumerable<ITicket>>>();
getTicketTasks.Add(Model.GetTicketsAsync(eventDate));
getTicketTasks.Add(Model.GetGuestTicketsAsync(eventDate));
...
getTicketTasks.Add(Model.GetOtherTicketsAsync(eventDate));

IEnumerable<ITicket>[] tickets = await Task.WhenAll(getTicketTasks);

In your case you create a task, but you don't start it so it doesn't run. If you did start it you would simply fire your actual asynchronous operations without storing the returned task anywhere. That means that you have nothing to await . All the tasks you are awaiting do is fire and forget another async operation.

Task.WhenAll also has an overload with params so another option would be:

var tickets = await Task.WhenAll(
    Model.GetTicketsAsync(eventDate),
    Model.GetGuestTicketsAsync(eventDate),
    Model.GetOtherTicketsAsync(eventDate));

* Or in any other case for that matter.

You've just created the Task . You never started it. Creating a Task via its constructor will not start the Task and hence will not transform to completed state either. So awaiting it will take forever.

Use Task.Run or call Task.Start however calling Task.Start isn't recommended. Prefer Task.Run to start a asynchronous operation. If you already have Task<T> simply create a array and await it.

var getTicketTasks = new List<Task<IEnumerable<ITicket>>>();
getTicketTasks.Add(Model.GetTicketsAsync(eventDate));
getTicketTasks.Add(Model.GetGuestTicketsAsync(eventDate));
...
getTicketTasks.Add(Model.GetOtherTicketsAsync(eventDate));
IEnumerable<ITicket>[] tickets = await Task.WhenAll(getTicketTasks);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM