Search code examples
c#.netfunc

How to convert IEnumerable<Task<T>> to IEnumerable<Func<Task<T>>> in C#?


I have a private function which takes IEnumerable<Func<Task<T>>> as input. I'm having IEnumerable<Task<T>> to be passed. How to convert IEnumerable<Task<T>> to IEnumerable<Func<Task<T>>>?

Code Sample:

private static async Task<IEnumerable<T>> ParallelizeAsync<T>(IEnumerable<Func<Task<T>>> funcs, int maxParallelism)
{
    var sem = new SemaphoreSlim(maxParallelism, maxParallelism);
    var result = funcs.Select(async f =>
    {
        await sem.WaitAsync();
        var r = await f();
        sem.Release();
        return r;
    });
    return await Task.WhenAll(result);
}

var functasks = Enumerable.Range(1, 5).Select(async x => await Task.FromResult(x));
var help = ParallelizeAsync<IEnumerable<int>>(functasks, 10);

I'm getting the following error,

cannot convert from 'System.Collections.Generic.IEnumerable<System.Threading.Tasks.Task>' to 'System.Collections.Generic.IEnumerable<System.Func<System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable>>>'

Am I missing some cast?


Solution

  • So, you'll want to create a Func which, when called, returns that already-completed Task you constructed. The easist way is simply:

    () => theTask
    

    So either:

    var functasks = Enumerable.Range(1, 5).Select(x => () => Task.FromResult(x));
    

    Or given functasks:

    var help = ParallelizeAsync<int>(functasks.Select(x => () => x), 10);
    

    Your other problem is that you're calling:

    var help = ParallelizeAsync<IEnumerable<int>>(functasks, 10)
    

    Since the signature of ParallelizeAsync is:

    private static async Task<IEnumerable<T>> ParallelizeAsync<T>(IEnumerable<Func<Task<T>>> funcs, int maxParallelism)
    

    This means that T is an IEnumerable<int>, so ParallelizeAsync is expecting an IEnumerable<Func<Task<IEnumerable<int>>>>. This doesn't match the rest of your question.

    You probably intended to call ParallelizeAsync<int>(...).