Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use await in a loop

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?

public class Program 
{
    public 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;
    }

}
like image 298
Satish Avatar asked Oct 17 '13 15:10

Satish


People also ask

Can you use await in a while loop?

Async & Await in a JavaScript While Loop Just like the for loop, the JavaScript while loop can use async/await too.

How do I run async await in for loop?

You can use a for-of loop or a for/while loop, it doesn't really matter which one you pick. (async() => { data = [1, 2, 3, 4, 5]; for (let e of data) { const i = await somePromiseFn(e); console. log(i); } console.

Can I use await in for loop C#?

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 Task s and then await ing them all with Task.

Does for loop wait for await?

Using await inside a for loop will cause the code to stop and wait for the asynchronous operation to complete before continuing. This means that all promises will be run sequentially.


3 Answers

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);
}
like image 184
Tim S. Avatar answered Oct 07 '22 02:10

Tim S.


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));
like image 41
SLaks Avatar answered Oct 07 '22 00:10

SLaks


public async Task<bool> Init()
{
    var series = Enumerable.Range(1, 5);
    Task.WhenAll(series.Select(i => DoWorkAsync(i)));
    return true;
}
like image 13
Vladimir Avatar answered Oct 07 '22 02:10

Vladimir