Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I use Async with ForEach?

Tags:

c#

async-await

Is it possible to use Async when using ForEach? Below is the code I am trying:

using (DataContext db = new DataLayer.DataContext())
{
    db.Groups.ToList().ForEach(i => async {
        await GetAdminsFromGroup(i.Gid);
    });
}

I am getting the error:

The name 'Async' does not exist in the current context

The method the using statement is enclosed in is set to async.

like image 331
James Jeffery Avatar asked Oct 10 '22 20:10

James Jeffery


People also ask

Can I use async with forEach?

forEach is not designed for asynchronous code. (It was not suitable for promises, and it is not suitable for async-await.) For example, the following forEach loop might not do what it appears to do: const players = await this.

How do I use async inside forEach?

forEach(async (element, index) => { // let result = await element; // console. log(result); // }) // This works well for (const element of myPromiseArray) { let result = await element; console. log(result) } console. log('After For Each Loop') } main();

Is forEach loop asynchronous in JavaScript?

forEach loop is not asynchronous. The Array. prototype. forEach method accepts a callback as an argument which can be an asynchronous function, but the forEach method will not wait for any promises to be resolved before moving onto the next iteration.

Can we use async await in forEach C#?

ForEach doesn't play particularly well with async (neither does LINQ-to-objects, for the same reasons). In this case, I recommend projecting each element into an asynchronous operation, and you can then (asynchronously) wait for them all to complete.


1 Answers

List<T>.ForEach doesn't play particularly well with async (neither does LINQ-to-objects, for the same reasons).

In this case, I recommend projecting each element into an asynchronous operation, and you can then (asynchronously) wait for them all to complete.

using (DataContext db = new DataLayer.DataContext())
{
    var tasks = db.Groups.ToList().Select(i => GetAdminsFromGroupAsync(i.Gid));
    var results = await Task.WhenAll(tasks);
}

The benefits of this approach over giving an async delegate to ForEach are:

  1. Error handling is more proper. Exceptions from async void cannot be caught with catch; this approach will propagate exceptions at the await Task.WhenAll line, allowing natural exception handling.
  2. You know that the tasks are complete at the end of this method, since it does an await Task.WhenAll. If you use async void, you cannot easily tell when the operations have completed.
  3. This approach has a natural syntax for retrieving the results. GetAdminsFromGroupAsync sounds like it's an operation that produces a result (the admins), and such code is more natural if such operations can return their results rather than setting a value as a side effect.
like image 254
Stephen Cleary Avatar answered Oct 16 '22 23:10

Stephen Cleary