3

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?

1
  • Can't you move await func(); out of the StartNew method? Commented Dec 24, 2013 at 11:16

3 Answers 3

11

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.

Sign up to request clarification or add additional context in comments.

Comments

4

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.

3 Comments

Thank you so much, both explanations and code was very useful! However, I still have a problem. “await” doesn't wait for the completion of call. Here is my code: Task<int> response = GetIntAsync(); int a = await response; Thanks ahead;
@user1662033, I'm not sure what you mean under await doesn't wait for the completion of the call. If you need a real blocking wait rather than an asynchronous continuation, you use task.Wait() instead of await task, although it's usually a sign of the bad code workflow design. Here's a test console app that works. Note testTask.Wait() inside Main(), it's there because Main is the app's entry point which cannot be async. Do read Stephen's Async Intro blog post, it's very helpful.
Also, I agree with @StephenCleary's answer that you most likely don't need to create a separate task with Task.Factory.StartNew or Task.Run inside GetIntAsync. Normally, you'd do it if you wanted to perform some lengthy CPU-bound work (some code..) inside GetIntAsync (to avoid blocking the UI when GetIntAsync itself is called on the main UI thread). That doesn't seem to be the case here.
3

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;
   });
}

2 Comments

I think you should also explan why did you change Task.Factory.StartNew() to Task.Run().

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.