user19608503
user19608503

Reputation:

Parallel.ForAsync in C# .NET?

I want to execute a for loop in C# in parallel asynchronously. But the Parallel class contains only a synchronous For method and an asynchronous ForEachAsync method (.NET 6). This looks like an oversight to me.

Where is the Parallel.ForAsync method? Is there any workaround?

Upvotes: 3

Views: 2619

Answers (3)

user22779599
user22779599

Reputation:

I agree,
not having a Parallel.ForAsync method looks like an enormous oversight. I have good news for you though: in .NET 8 and C#12 (coming out soon at 23. november 2023) this will be resolved. Parallel.ForAsync

Upvotes: 9

Dmitrii Bychenko
Dmitrii Bychenko

Reputation: 186813

Well, if you can't wait / use .NET 8, you can try to mimic ForAsync with a help of ForEachAsync which is supported from .NET 6 on. To loop over some enumerable (array, list, etc.) while having index:

// Must be IEnumerable<T>
var data = ...;

await Parallel.ForEachAsync(data.Select((value, index) => (value, index)), 
                            async (pair, token) => {
  var value = pair.value;
  var index = pair.index;

  //TODO: relevant code here
});

If you want to have async version for for (int i = 0; i < n; ++i) loop then

int n = ...;

await Parallel.ForEachAsync(Enumerable.Range(0, n), async (i, token) => { 
  //TODO: relevant code here
});

Upvotes: 4

Theodor Zoulias
Theodor Zoulias

Reputation: 43845

The Parallel.ForAsync API will be available starting from .NET 8 (release scheduled for November 14, 2023). It has the three following overloads:

public static Task ForAsync<T>(T fromInclusive, T toExclusive,
    Func<T, CancellationToken, ValueTask> body)
    where T : notnull, IBinaryInteger<T>;

public static Task ForAsync<T>(T fromInclusive, T toExclusive,
    CancellationToken cancellationToken, Func<T, CancellationToken, ValueTask> body)
    where T : notnull, IBinaryInteger<T>;

public static Task ForAsync<T>(T fromInclusive, T toExclusive,
    ParallelOptions parallelOptions, Func<T, CancellationToken, ValueTask> body)
    where T : notnull, IBinaryInteger<T>;

It is the first public .NET API to be based on the generic math interfaces introduced in .NET 7.

Usage example:

ParallelOptions options = new() { MaxDegreeOfParallelism = 2 };

await Parallel.ForAsync(0, 100, options, async (i, ct) =>
{
   // Process the i element (here the type of i is int)
});

More information and benchmarks about this API can be found in this Microsoft document. Also here is the API proposal.

Upvotes: 3

Related Questions