How to use await in a loop

no-await-in-loop
await in for loop javascript
foreach async/await
javascript wait for foreach to finish
hack await in loop
synchronous for loop javascript
promise.all for loop
await on for loop nodejs

I'm trying to create an asynchronous console app that does a some work on a collection. I have one version which uses parallel for loop another version that uses async/await. I expected the async/await version to work similar to parallel version but it executes synchronously. What am I doing wrong?

class Program
{
    static void Main(string[] args)
    {
        var worker = new Worker();
        worker.ParallelInit();
        var t = worker.Init();
        t.Wait();
        Console.ReadKey();
    }
}

public class Worker
{
    public async Task<bool> Init()
    {
        var series = Enumerable.Range(1, 5).ToList();
        foreach (var i in series)
        {
            Console.WriteLine("Starting Process {0}", i);
            var result = await DoWorkAsync(i);
            if (result)
            {
                Console.WriteLine("Ending Process {0}", i);
            }
        }

        return true;
    }

    public async Task<bool> DoWorkAsync(int i)
    {
        Console.WriteLine("working..{0}", i);
        await Task.Delay(1000);
        return true;
    }

    public bool ParallelInit()
    {
        var series = Enumerable.Range(1, 5).ToList();
        Parallel.ForEach(series, i =>
        {
            Console.WriteLine("Starting Process {0}", i);
            DoWorkAsync(i);
            Console.WriteLine("Ending Process {0}", i);
        });
        return true;
    }
}

The way you're using the await keyword tells C# that you want to wait each time you pass through the loop, which isn't parallel. You can rewrite your method like this to do what you want, by storing a list of Tasks and then awaiting them all with Task.WhenAll.

public async Task<bool> Init()
{
    var series = Enumerable.Range(1, 5).ToList();
    var tasks = new List<Task<Tuple<int, bool>>>();
    foreach (var i in series)
    {
        Console.WriteLine("Starting Process {0}", i);
        tasks.Add(DoWorkAsync(i));
    }
    foreach (var task in await Task.WhenAll(tasks))
    {
        if (task.Item2)
        {
            Console.WriteLine("Ending Process {0}", task.Item1);
        }
    }
    return true;
}

public async Task<Tuple<int, bool>> DoWorkAsync(int i)
{
    Console.WriteLine("working..{0}", i);
    await Task.Delay(1000);
    return Tuple.Create(i, true);
}

JavaScript loops - how to handle async/await, Asynchronous loops. How to use await inside a loop? Let's just write async function and await each task. async function processArray(array)  Await in a forEach loop We’ll do the same thing as we did in the for-loop example. First, let’s loop through the array of fruits. const forEachLoop = _ => { console.log('Start') fruitsToGet.forEach(fruit => { // Send a promise for each fruit }) console.log('End') }

Your code waits for each operation (using await) to finish before starting the next iteration. Therefore, you don't get any parallelism.

If you want to run an existing asynchronous operation in parallel, you don't need await; you just need to get a collection of Tasks and call Task.WhenAll() to return a task that waits for all of them:

return Task.WhenAll(list.Select(DoWorkAsync));

no-await-in-loop - Rules - ESLint, This rule disallows the use of await within loop bodies. Examples. Examples of correct code for this rule: async function foo(things)  There are three steps to use await and filter properly: 1. Use map to return an array promises. 2. await the array of promises. 3. filter the resolved values

public async Task<bool> Init()
{
    var series = Enumerable.Range(1, 5);
    Task.WhenAll(series.Select(i => DoWorkAsync(i)));
    return true;
}

In JavaScript, does using await inside a loop block the loop?, Does await block the loop? Or does the i continue to be incremented while await ing? "Block" is not the right word, but yes, i does not continue to be incremented  1. If you want to execute await calls in series, use a for-loop (or any loop without a callback). 2. Don't ever use await with forEach. Use a for-loop (or any loop without a callback) instead. 3. Don't await inside filter and reduce. Always await an array of promises with map, then filter or reduce accordingly. This article was originally posted on my blog.

In C# 7.0 you can use semantic names to each of the members of the tuple, here is Tim S.'s answer using the new syntax:

public async Task<bool> Init()
{
    var series = Enumerable.Range(1, 5).ToList();
    var tasks = new List<Task<(int Index, bool IsDone)>>();

    foreach (var i in series)
    {
        Console.WriteLine("Starting Process {0}", i);
        tasks.Add(DoWorkAsync(i));
    }

    foreach (var task in await Task.WhenAll(tasks))
    {
        if (task.IsDone)
        {
            Console.WriteLine("Ending Process {0}", task.Index);
        }
    }

    return true;
}

public async Task<(int Index, bool IsDone)> DoWorkAsync(int i)
{
    Console.WriteLine("working..{0}", i);
    await Task.Delay(1000);
    return (i, true);
}

You could also get rid of task. inside foreach:

// ...
foreach (var (IsDone, Index) in await Task.WhenAll(tasks))
{
    if (IsDone)
    {
        Console.WriteLine("Ending Process {0}", Index);
    }
}
// ...

Asynchronous Process inside a javascript for loop, through a block of code while a specified condition is true. 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

Understanding async-await in JavaScript, Sure the code does work, but I'm pretty sure it doesn't do what you expect it to do. It just fires off multiple asynchronous calls, but the printFiles function does  Disallow await inside of loops (no-await-in-loop). Performing an operation on each element of an iterable is a common task. However, performing an await as part of each operation is an indication that the program is not taking full advantage of the parallelization benefits of async/await.

JavaScript for/in Statement, Using async/await while looping through arrays in Javascript loop seems simple, but there's some non-intuitive behavior to look out for when  async functions return a Promise, which is an object that will eventually "resolve" to a value, or "reject" with an error. The await keyword means to wait until this value (or error) has been finalized. So from the perspective of the running function, it blocks waiting for the result of the slow async function.

Using async/await with a forEach loop, The Bad. The bad way of using await within an for-loop is how I always handled this task until I worked on a project  This little extension method should give you exception-safe async iteration: public static async Task ForEachAsync<T> (this List<T> list, Func<T, Task> func) { foreach (var value in list) { await func(value); } } Since we're changing the return type of the lambda from void to Task, exceptions will propagate up correctly.

Comments
  • I don't know about others, but a parallel for/foreach seems more straight forward for parallel loops.
  • Important to note that when you see the Ending Process notification isn't when the task is actually ending. All of those notifications are dumped out sequentially right after the last of the tasks finishes. By the time you see "Ending Process 1", process 1 might have been over for a long time. Other than the choice of words there, +1.
  • @Brettski I may be wrong, but a parallel loop traps any sort of async result. By returning a Task<T> you immediately get back a Task object in which you can manage the work that is going on inside such as cancelling it or seeing exceptions. Now with Async/Await you can work with the Task object in a more friendly manner - that is you don't have to do Task.Result.
  • @Tim S, what if I want to return a value with async function using Tasks.WhenAll method?
  • Would it be a bad practice to implement a Semaphore in DoWorkAsync to limit the maximum executing tasks?
  • so you cant use any asynchronous methods in any loops?
  • @Satish: You can. However, await does the exact opposite of what you want – it waits for the Task to finish.
  • I wanted to accept your answer but Tims S has a better answer.
  • Or if you don't need to know when the task finished you can just call the methods without awaiting for them
  • To confirm what that syntax is doing - it's running the Task called DoWorkAsync on each item in list (passing each item into DoWorkAsync, which I assume has a single parameter)?