I have a question about parallel execution of the async methods.
I want to limit number of async methods that will be executed simultaneously (to limit number of web requests to another system, which are actually sent in the async method).
So what is the best way to do that ? I found a solution by using Parallel, and setting DegreeOfParallelism, but I don't really like this solution, because it will block number of threads equal to DOP (degree of parallelism).
So, here is the code with Parallel:
var results = dataProvider.GetResults(someIdParam);
var average = results.AsParallel().WithDegreeOfParallelism(5).Average(x =>
{
var t = GetSSIM(x);
t.Wait();
return t.Result;
});
So, this will work and limit number of simultaneous requests, but will block 5 threads.
I ended up writing my own method:
public static async Task<IEnumerable<T2>> ProcessEachAsync<T1, T2>(IEnumerable<T1> src, Func<T1, Task<T2>> func, int dop)
{
var workers = new Task<T2>[Math.Min(dop, src.Count())]; //to make sure that we will not have nulls in workers collection
var result = new List<T2>();
int counter = 0;
int index = 0;
foreach(var element in src)
{
if (counter < dop)
index = counter++;
else
{
var ended = await Task.WhenAny(workers);
index = Array.FindIndex(workers, x => x == ended);
result.Add(ended.Result);
}
var t = func(element);
t.Start();
workers[index] = t;
}
Task.WaitAll(workers);
result.AddRange(workers.Select(x => x.Result));
return result;
}
CAUTION!!!!! This code is not yet tested and have bugs!!!! But it explains main idea
So, this solution will block only 1 thread. Maybe there is simpler way to achieve what I want?