As @Sriram Sakthivel pointed out, there are some problems using Parallel.ForEach with asynchronous lambdas. Stephen Tub ForEachASync can do the equivalent. He talks about it here , but here is the code:
public static class Extensions { public static Task ForEachAsync<T>(this IEnumerable<T> source, int dop, Func<T, Task> body) { return Task.WhenAll( from partition in Partitioner.Create(source).GetPartitions(dop) select Task.Run(async delegate { using (partition) while (partition.MoveNext()) await body(partition.Current); })); } }
It uses the Partitioner class to create a load balancer ( doco ) and allows you to specify how many threads you want to run with the dop parameter. to see the difference between it and Parallel.ForEach . Try the following code.
class Program { public static async Task GetStuffParallelForEach() { var data = Enumerable.Range(1, 10); Parallel.ForEach(data, async i => { await Task.Delay(1000 * i); Console.WriteLine(i); }); } public static async Task GetStuffForEachAsync() { var data = Enumerable.Range(1, 10); await data.ForEachAsync(5, async i => { await Task.Delay(1000 * i); Console.WriteLine(i); }); } static void Main(string[] args) {
if you run GetStuffForEachAsync , the program waits for the completion of all work. If you run GetStuffParallelForEach , the Finished line will be printed before completion.
Ned stoyanov
source share