0

I have a scenario where I need to run 3 async methods parallel, I am doing it as following:

using (Method1 m1 = new Method1())
using (Method2 m2 = new Method2())
using (Method3 m3 = new Method3())
{
    var T_1 = m1.FETCH(); // 10 Seconds
    var T_2 = m2.FETCH(); // 2 Seconds
    var T_3 = m3.FETCH(); // 30 Seconds
}
// ALL 3 STARTED
await Task.WhenAll(T_1, T_2, T_3);
var result_1 = await T_1;
var result_2 = await T_2;
var result_3 = await T_3;
// AL 3 FINISHED - Total time 42 seconds

This works fine, once all 3 of them are finish I can load the next 3

using (Method4 m4 = new Method4())
using (Method5 m5 = new Method5())
using (Method6 m6 = new Method6())
{
    var T_4 = m1.FETCH(); // 10 Seconds
    var T_5 = m2.FETCH(); // 2 Seconds
    var T_6 = m6.FETCH(); // 30 Seconds
}
// ALL 3 STARTED
await Task.WhenAll(T_4, T_5, T_6);
var result_4 = await T_4;
var result_5 = await T_52;
var result_6 = await T_6;
// AL 3 FINISHED - Total time 42 seconds

What I want to do it is, run it in a way that it runs 3 tasks parallel at any given time. I want it to run T_1, T_2 and T_3 and as T2 only task 2 seconds as soon as it is finish load T_4 into it instead of waiting for all 3 to finished but Only 3 Max at any given time.

How can I achieve that behaviour?

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Ali
  • 2,702
  • 3
  • 32
  • 54
  • 2
    There's an example of a limited concurrency task scheduler given in the documentation for [`TaskScheduler`](https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.taskscheduler?view=net-5.0) – Damien_The_Unbeliever May 20 '21 at 07:48
  • Try adding then in a tasks list and then Task.WhenAll(tasks.AsParallel().Select(async task => await task())); – Indrit Kello May 20 '21 at 07:51
  • https://stackoverflow.com/questions/25398178/execute-in-parallel-with-limited-concurency – Matthew Watson May 20 '21 at 07:54
  • https://stackoverflow.com/questions/38634376/running-async-methods-in-parallel/38634509 you can find your answer here – Shah May 20 '21 at 09:52
  • and guys I am aware of the existing similar questions, but none of them mentioned `SemaphoreSlim` which Stephen Cleary's answer covered. So this is a legit question for someone using .net 4.* so I will debate against this being a duplicate :) – Ali May 24 '21 at 10:33

1 Answers1

4

Only 3 Max at any given time.

The normal way of doing asynchronous concurrency (terminology note: not parallelism) is to use SemaphoreSlim:

var throttler = new SemaphoreSlim(3);
var task1 = Throttled(m1.FetchAsync);
var task2 = Throttled(m2.FetchAsync);
var task3 = Throttled(m3.FetchAsync);
var task4 = Throttled(m4.FetchAsync);
var task5 = Throttled(m5.FetchAsync);
var task6 = Throttled(m6.FetchAsync);
await Task.WhenAll(tasks);

async Task<T> Throttled<T>(Func<Task<T>> operation)
{
  await throttler.WaitAsync();
  try { return await operation(); }
  finally { throttler.Release(); }
}
Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810