Awaiting tasks from multiple objects

c# await multiple tasks return value
c# run multiple tasks in parallel
c# start multiple tasks simultaneously
make multiple web requests in parallel c#
c# run multiple async tasks in parallel
c# call multiple methods asynchronously
httpclient multiple requests c#
c# task

I have an application that uses MEF to load plugins. All of these plugins conform to the following interface:

public interface IPlugin {
    Task Start();
}

All the methods are implemented as async: public async Task Start()

When the application is running I have an IEnumerable<IPlugin> property available with all the plugins. The question is basically how I can run all the Start() methods in parallel and wait until all methods are finished?

I know about Parallel.ForEach(plugins, plugin => plugin.Start()), but this is not awaitable and execution continues before all plugins are started.

The most promising solution seems to be Task.WhenAll(), but I don't know how to send in an unknown list of methods into this without adding some scaffolding (which seems like overhead).

How can I accomplish this?

And here's a one-liner:

await Task.WhenAll(plugins.Select(p => p.Start()));

The plugins will run asynchronously, but not in parallel. If you want for some reason to dispatch plugins to thread pool explicitly, you may add Task.Run with async lambda into Select.

c# - Awaiting tasks from multiple objects, And here's a one-liner: await Task.WhenAll(plugins.Select(p => p.Start()));. The plugins will run asynchronously, but not in parallel. If you want  Waiting for Multiple Objects. 05/31/2018; 2 minutes to read; In this article. The following example uses the CreateEvent function to create two event objects and the CreateThread function to create a thread. It then uses the WaitForMultipleObjects function to wait for the thread to set the state of one of the objects to signaled using the

You can do:

var tasks = new List<Task>();
foreach(var plugin in plugins) 
{
   var task = plugin.Start();
   tasks.Add(task);
}
await Task.WhenAll(tasks); 

Start Multiple Async Tasks and Process Them As , WhenAny, you can start multiple tasks at the same time and process them In each iteration of a while loop, an awaited call to WhenAny returns the private async void startButton_Click(object sender, RoutedEventArgs e)  The code above is very similar to the code snippet at the top of the article, the difference is that the await keyword is used in a different way. When the method is called, the first thing we need to do is create a collection of tasks (as our method returns a Task which is the async way of saying returns void).

You could use Microsoft's Reactive Framework to ensure that this is awaitable, happens asynchronously and in parallel.

await
    plugins
        .ToObservable()
        .SelectMany(plugin => Observable.FromAsync(() => plugin.Start()))
        .ToArray();

How to make multiple web requests in parallel by using async and , The await operator is applied to the task at the point in the method The method declares an HttpClient object,which you need to access  List<Task<int>> downloadTasks = downloadTasksQuery.ToList(); Add a while loop that performs the following steps for each task in the collection: Awaits a call to WhenAny to identify the first task in the collection to finish its download. Task<int> firstFinishedTask = await Task.WhenAny(downloadTasks); Removes that task from the collection.

As you can see Start method returns a Task. I would define a list of plugin loading tasks and check with Task.WhenAll when every task is completed. After that you can assume all Start methods have returned.

List<IPlugin> plugins = ... 
var pluginsLoadingTasks = new List<Task>();

foreach(var plugin in plugins)
{
    pluginsLoadingTasks.Add(plugin.Start());
}

// It's not necessary to check if pluginsLoadingTasks is empty, 
// because WhenAll won't throw an exception in that case
await Task.WhenAll(pluginsLoadingTasks);
// You can assume all Start methods have completed

I suggest you to read the differences between Task.WhenAll and Parallel.ForEach constructs.

Professional C# 6 and .NET Core 1.0, MultipleAsyncMethods could return the result faster if await is not used with Task combinators accept multiple Task objects as parameter and return a Task. If the antecedent is a System.Threading.Tasks.Task<TResult> object, and the task ran until it was completed, then the continuation can access the Task<TResult>.Result property of the task. The Task<TResult>.Result property blocks until the task has completed. However, if the task was canceled or faulted,

Dreaming of multiple tasks, That's the case which the await keyword makes particularly easy to work with. have a large number of items to deal with, possibly dynamically generated We want to execute multiple tasks in parallel (which may or may not  It turns out that awaiting execution from methods invoked within the action method really has nothing to do with automagically wrapping returned objects into Tasks. It’s solely the combination of the async keyword with returned Task<T> that enables this syntactical sugar. Here, we combine async with Task<T> to automatically wrap returned

Pro C# 5.0 and the .NET 4.5 Framework, private async void btnGallMethod_Click(object sender, EventArgs e) this. Text = await DoworkAsync.(); } private async Taskstring DoworkAsync () return await Task. Async Methods with Multiple Awaits It is completely permissible for a single  The task is assigned to the integerTask variable in the example. Because integerTask is a Task<TResult>, it contains a Result property of type TResult. In this case, TResult represents an integer type. When await is applied to integerTask, the await expression evaluates to the contents of the Result property of integerTask.

Trio's core functionality, (Informally we say that a task that does this is “hogging the run loop”.) If you call an async function provided by Trio ( await <something in trio> ), and it This is a special exception which encapsulates multiple exception objects – either  The method declares an HttpClient object,which you need to access method GetByteArrayAsync in ProcessURLAsync. The method creates and starts three tasks of type Task<TResult>, where TResult is an integer. As each task finishes, DisplayResults displays the task's URL and the length of the downloaded contents. Because the tasks are running asynchronously, the order in which the results appear might differ from the order in which they were declared.

Comments
  • Son of a bench, it's been staring me in the face this whole time! Would you care to elaborate on "The plugins will run asynchronously, but not in parallel" ?
  • You can output CurrentThread's id and you will see that plugins at least start on a single thread. Here's a nice article about it: blogs.msdn.microsoft.com/benwilli/2015/09/10/…
  • @Sergey.quixoticaxis.Ivanov For running in parallel, might it not be better to use AsParallel() (as in plugins.AsParallel().Select(p => p.Start())) instead of Task.Run? See here.
  • @pere57 I doubt it will make any difference. Also I'm not certain that plugins can get any value out of work "chunking" inside parallel query. It should be measured irl, what is better for this case.
  • My pet peeve is if(collection.Count > 0) - use if(collection.Any()). You don't care how many items, just 'is there any?'.
  • @Neil, very good suggestion! I always keep forgetting that Any() is more efficient in this case. :)
  • Or you can ommit Any check as WhenAll can work with zero tasks.
  • Also you probably meant Task.WhenAll, not Tasks.WhenAll
  • @Sergey.quixoticaxis.Ivanov, I didn't know you could pass an empty collection to it, so thanks for the suggestion.
  • How is your answer different from what Frank suggested?