thiag0
thiag0

Reputation: 2229

How to use Task.Factory.StartNew<TResult> when TResult is a Task<object>

Running into a bit of a roadblock using the Task Parallel Library to call a method that returns a Task.

I have a class called MspClient which contains an async method called MakeMspCallAsync

public class MspClient
{        
    public async Task<IMspCallResponse> MakeMspCallAsync(IMspCallRequest request)
    {
        var response = new MspCallResponse();
        ... 
        await ...
        ...
        return response;
    }
}  

In my program that uses the MspClient class, I want to write something along these lines:

using (var mspClient = new MspClient())
{
    Task<IMspCallResponse>[] tasks = new Task<IMspCallResponse>[ctx.Message.MspCallRequests.Count];

    for(int i = 0; i < ctx.Message.MspCallRequests.Count; i++)
    {
        var mspCallRequest = ctx.Message.MspCallRequests[i];        
        tasks[i] = Task.Factory.StartNew<IMspCallResponse>(mspClient.MakeMspCallAsync(mspCallRequest));
    }

    Task.WaitAll(tasks);
}

The compile time exception occurs on this line:

tasks[i] = Task.Factory.StartNew<IMspCallResponse>(mspClient.MakeMspCallAsync(mspCallRequest));

Error   1   The best overloaded method match for 'System.Threading.Tasks.TaskFactory.StartNew<IMspCallResponse>(System.Func<IMspCallResponse>)' has some invalid arguments  

Error   2   Argument 1: cannot convert from 'System.Threading.Tasks.Task<IMspCallResponse>' to 'System.Func<IMspCallResponse>'

Pretty sure I'm overlooking something very simple but can't wrap my head around it, can someone please help me out? Thanks.

Upvotes: 1

Views: 285

Answers (1)

Mike Zboray
Mike Zboray

Reputation: 40838

You at least need a delegate in there:

Task.Factory.StartNew<IMspCallResponse>(() => mspClient.MakeMspCallAsync(mspCallRequest));

However this will return a Task<Task<IMspCallResponse>>, which is a little unweildy. You will need to unwrap it (see TaskExtensions.Unwrap). Task.Run is better because it will do that for you:

tasks[i] = Task.Run(() => mspClient.MakeMspCallAsync(mspCallRequest));

Upvotes: 2

Related Questions