Home > Software engineering >  How to await multiple tasks, that were created inside await foreach?
How to await multiple tasks, that were created inside await foreach?

Time:06-21

When using AsAsyncEnumerable and await foreach, each item is lazy loaded. Per item I want to call a method DoSomething, that returns Task. The method calls should happen in parallel. When all tasks complete, the below method should return Unit.

public async Task<Unit> Handle(SomeRequest request, CancellationToken cancellationToken)
{
    var entities = _dbContext.MyModel
        .Where(...)
        .AsAsyncEnumerable();

    await foreach (var item in entities)
    {
        _ = item.DoSomething();
    }

    return Unit.Value;
}

I am not sure how to await all tasks when using await foreach. Would this be the right approach?:

public async Task<Unit> Handle(SomeRequest request, CancellationToken cancellationToken)
{
    var entities = _dbContext.MyModel
        .Where(...)
        .AsAsyncEnumerable();

    List<Task> tasks = new();

    await foreach (var item in entities)
    {
        tasks.Add(item.DoSomething());
    }

    await Task.WhenAll(tasks);

    return Unit.Value;
}

CodePudding user response:

The given example should work, especially if you expect fairly few items.

Since you have no (visible) mechanism to limit the number of concurrent tasks you might suffer problems if you have a lots of items. You might for example exhaust the threadpool. If the amount of work done per item is very small it might also benefit from processing batches of items. To handle cases like these you might consider using something like DataFlow, it should allow you to specify the degree of parallelism.

  • Related