This is a follow up question from this question: How do you run a variable number of concurrent parametrizable infinite loop type of threads in C#?
Say I have a value taskLimit (assume 20), of no of simultaneous Tasks "MyTask" which are created in the RunAsync method below:
protected override async Task RunAsync(CancellationToken cancellationToken)
{
    var tasks = new List<Task>();
    try
    {
        for (int i = 0; i < taskLimit; i++)
        {
            tasks.Add(MyTask(cancellationToken, i);
        }
        
        await Task.WhenAll(tasks);
    }
    catch (Exception e)
    {
        //Exception Handling
    }
}
public async Task MyTask(CancellationToken cancellationToken, int a)
{
    while (true)
    {
        cancellationToken.ThrowIfCancellationRequested();
        try
        {
            //long running code, if possible check for cancellation using the token
            //Do something useful here. Very Processor and IO heavy. Takes 5-10 minutes to complete.
            //SomeHeavyTask can only concurrently run upto a limit of say 5. Implement a token system of sorts
            while(freeTokens<1)
            {
            await Task.Delay(TimeSpan.FromMinutes(1), cancellationToken);
            }
            freeTokens = freeTokens-1;
            SomeHeavyTask(cancellationToken);
            freeTokens = freeTokens+1;
            
            //sleep for an independently parameterizable period, then wake up and repeat
            await Task.Delay(TimeSpan.FromHours(parametrizableTaskDelay[i]), cancellationToken);
        }
        catch (Exception e)
        {
            //Exception Handling
        }
    }
}
Is it possible to do such a thing? Is there a better more formal approach supported natively in C# to achieve the same thing? Please note the essence of this question is that there are substantially less freeTokens than the taskLimit. And that each MyTask spends only 10% time in SomeHeavyTask(), and most of the time is spent in await Task.Delay().
 
     
     
     
    