Running parallel tasks until they're done The General Idea

I wish to simulate something which works like Java's ThreadExecutor, but as a first step, I would like to run a fixed number of identical tasks in parallel.
The next step should be queuing different tasks.

The method in question

public static async Task RunTasks(Func&lt;Task&lt;bool&gt;&gt; action, int tasks, int retries, string method)
{
    // Its just a source in order to use the library.
    byte[] source = new byte[tasks];

    // Wrapping the method with a retry mechanism
    async Task NewAction(byte _)
    {
        await DoWithRetries(async () =&gt; await action(), retries, method);
    }

    // Running everything
    await source.ParallelForEachAsync(NewAction, tasks);
}

private static async Task&lt;bool&gt; DoWithRetries(Func&lt;Task&lt;bool&gt;&gt; action, int retryCount, string method)
{
    while (true)
    {
        if (retryCount &lt;= 0)
            return false;

        try
        {
            bool res = await action();
            if (res)
                return true;
        }
        catch (Exception e)
        {
            LogFactory.General.Fatal(e, method);
        }

        retryCount--;
        await Task.Delay(200);
    }
}


External Libraries

I used the AsyncEnumerator Nuget (which allows the ParallelForEachAsync call)

Code Execution

int page = -1;
int tasks = 10;
long count = 0;

await RetryComponent.RunTasks(async () =&gt;
{
    int localPage = Interlocked.Increment(ref page);
    int results = -1;

    while (results != 0)
    {
        Console.WriteLine($"Page: {localPage}");

        // req.IsSuccess holds if the request processed well 
        // mData contains the data returned from db (List)
        var req = await FetchSomeListFromDb();
        if (!req.IsSuccess)
            continue;

        foreach (var item in req.mData)
        {
            // simluate some IO..
            Interlocked.Increment(ref count);
        }

        // shuts down if zero
        results = req.mData.Count;

        // next page
        localPage = Interlocked.Increment(ref page);
    }

    return true;

}, tasks, 1, MethodBase.GetCurrentMethod().Name);


The issues I have with this code:


It seems like someone 100% did it already in the past, but I couldn't find anything like that or like the Java's ThreadsExecutor I mentioned
It seems like the execution code (The code I used to run everything) is large and seems like it will repeat itself..especially the page increment and the while handling (the last 2 statements at the end of the while block)


I will be glad to get a feedback on it or suggestions if the code exists somewhere (Either my implemetation or something similar to Java's ThreadsExecutor)
1) The library you are trying to use clearly does not fit your requirements. So why force it? Aren't you essentially just calling:

var tasks = Enumerable.Range(0, tasks).Select(i =&gt; DoWithRetries(action, retries, method));
await Task.WhenAll(tasks);


2) Fatal error is an error that your software cannot recover from. If you just swallow it in retry loop and keep going, then it is not fatal.

3) Delay duration should probably be a parameter and not a hardcoded value.

4) You can use nameof operator instead of MethodBase.GetCurrentMethod().Name.

P.S. I don't know what ThreadExecutor is and I didn't understand your use-case example, so I won't comment on those.