Any dot in List <T> .ForEach () with Async?
I came across this piece of code:
items.ForEach(async item => { doSomeStuff(); await mongoItems.FindOneAndUpdateAsync(mongoMumboJumbo); await AddBlah(SqlMumboJumbo); }); Does it make sense to make this a .forEach delegate, or could it be a regular foreach loop? While the function containing the loop is in async, will it be async by default?
The delegate obtained by ForEach is Action<T> :
public void ForEach(Action<T> action) This means that any asynchronous delegate that you use inside it will effectively turn into an async void method. This is a fire and oblivion style. This means that your foreach will not finish waiting asynchronously before continuing to invoke the delegate in the next item in the list, which may be an undesirable behavior.
Use regular ForEach instead.
Side note - foreach VS ForEach by Eric Lippert, great blog post.
You do not know when your function is finished, or the result of the function. If you start each calculation in a separate task, you can wait for Task.WhenAll and interpret the results, even throwing exceptions:
private async Task ActionAsync(T item) { doSomeStuff(); await mongoItems.FindOneAndUpdateAsync(mongoMumboJumbo); await AddBlah(SqlMumboJumbo); } private async Task MyFunction(IEnumerable<T> items) { try { foreach (var item in items) { tasks.Add( ActionAsync(item) ) } // while all actions are running do something useful // when needed await for all tasks to finish: await Task.WhenAll(tasks); // interpret the result of each action using property Task.Result } catch (AggregateException exc) { ProcessAggregateException(exc); } } An aggregateException expression occurs when any of your tasks throw an exception. If contains all the exceptions thrown by all your tasks.