Jeff Glazier
Jeff Glazier

Reputation: 53

Parallel execution of a loop that uses async

I'm writing a Windows service and am looking for a way to execute a number of foreach loops in parallel, where each loop makes a call to an asynchronous (TAP) method. I initially tried the following code, which doesn't work because Parallel.ForEach and async/await are not compatible. Does anyone know whether there is an alternate approach that can achieve this?

Parallel.ForEach(messagesByFromNumber, async messageGroup =>
{
    foreach (var message in messageGroup)
    {
        await message.SendAsync();
    }
});

For the sake of clarity, due to the way that SendAsync() operates, each copy of the foreach loop must execute serially; in other words, the foreach loop cannot become concurrent / parallel.

Upvotes: 4

Views: 2515

Answers (2)

Serge Semenov
Serge Semenov

Reputation: 10042

You can make it more cleat with AsyncEnumerator NuGet Package:

using System.Collections.Async;

await messagesByFromNumber.ParallelForEachAsync(async messageGroup =>
{
    foreach (var message in messageGroup)
    {
        await message.SendAsync();
    }
}, maxDegreeOfParallelism: 10);

Upvotes: 0

i3arnon
i3arnon

Reputation: 116548

There's no need to use Parallel.Foreach if your goal is to run these concurrently. Simply go over all your groups, create a task for each group that does a foreach of SendAsync, get all the tasks, and await them all at once with Task.WhenAll:

var tasks = messagesByFromNumber.Select(async messageGroup =>
{
    foreach (var message in messageGroup)
    {
        await message.SendAsync();
    }
});
await Task.WhenAll(tasks)

Upvotes: 5

Related Questions