Ofek Agmon
Ofek Agmon

Reputation: 5198

Return async task which is using another async function

I am trying to return Task paremeter in a function that uses async function and got in trouble.

Here is my code:

 private async Task<int> GetIntAsync()
 {
   return Task<int>.Factory.StartNew(async () =>
   {
       await func();

       some code..

       return 123;
   });

 }

I get the error: "cannot convert async lambda expression to delegate type"..

Is there any way to do call the async functnion from the new task?

Upvotes: 3

Views: 5829

Answers (3)

Stephen Cleary
Stephen Cleary

Reputation: 456417

You almost certainly do not want to call Task.Factory.StartNew or Task.Run. Instead, just use async and await:

private async Task<int> GetIntAsync()
{
   await func();

   some code..

   return 123;
}

For more information, see my async intro blog post.

Upvotes: 11

noseratio
noseratio

Reputation: 61666

I'd like to show how you could correct your initial syntax to resolve the compiler error and still keep the same signature of the GetIntAsync method:

private async Task<int> GetIntAsync()
{
    return await Task.Factory.StartNew(async () =>
    {
        await Task.Delay(42);
        return 123;
    }).Unwrap();
}

Here is the same code with a bit more explicit typing, so you could better understand what's going on:

private async Task<int> GetIntAsync()
{
    Func<Task<int>> lambda = async () =>
    {
        await Task.Delay(42);
        return 123;
    };

    Task<Task<int>> outerTask = Task.Factory.StartNew(lambda);

    Task<int> innerTask = outerTask.Unwrap();

    return await innerTask;
}

Indeed, this approach is unnecessary complex and you have a redundant await here. The answer by @user2720372 suggests the right way of creating a task using Task.Run.

Upvotes: 4

w.b
w.b

Reputation: 11228

If you want to return Task<int> from your method you can't declare it as async because you don't await anything in it (you only await in the inner Task):

private Task<int> GetIntAsync()
{
    return Task.Run(async () =>
        {
            await Task.Delay(1000);
            return 123;
        });
}

or if you do await, the return type should be Task<Task<int>>:

private async Task<Task<int>> MyMethod()
{
   await Task.Delay(1000);

   return Task.Run(async () =>
   {
        await Task.Delay(1000);
        return 123;
   });
}

Upvotes: 3

Related Questions