Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between returning and awaiting a Task in an async method [duplicate]

Is there any difference between the methods below? Is one preferable over the other?

public static async Task SendAsync1(string to, string subject, string htmlBody) {
  // ...
  await smtp.SendMailAsync(message);
  // No return statement
}

public static Task SendAsync2(string to, string subject, string htmlBody) {
  // ...
  return smtp.SendMailAsync(message);
}

This method will be called from MVC controller methods; for example:

public async Task<ActionResult> RegisterUser(RegisterViewModel model)
{
  // ...
  await Mailer.SendAsync(user.Email, subject, body);
  return View(model);
}
like image 467
James Avatar asked Jun 08 '14 19:06

James


People also ask

Should you return the task or await?

The only time we truly want to await is when we do something with the result of the async task in the continuation of the method. Note that if we don't have return await, but return a Task<T> instead, the return happens right away, so, if the code is inside a try/catch block, the exception will not be caught.

Is an async method that returns task?

Async methods can have the following return types: Task, for an async method that performs an operation but returns no value. Task<TResult>, for an async method that returns a value. void , for an event handler.

What is the difference between task and async task?

Async methods are intended to be non-blocking operations. An await expression in an async method doesn't block the current thread while the awaited task is running. Instead, the expression signs up the rest of the method as a continuation and returns control to the caller of the async method.

What is the return type of async await?

The behavior of async / await is similar to combining generators and promises. Async functions always return a promise. If the return value of an async function is not explicitly a promise, it will be implicitly wrapped in a promise.


1 Answers

There are 2 practical differences:

  1. The second option will not create the state machine mecanism that allows for async-await usage. That will have a minor positive effect on performance.
  2. The exception handling would be a little different. When you mark a method as async any exceptions are stored in the returned task (both from the asynchronous part and the synchronous one) and thrown only when the task is awaited (or waited). When it's not async, the exceptions from the synchronous parts act just like in any other method.

My suggestion: Use the second one for the added performance boost but keep an eye out for exceptions and bugs.


An example that shows the difference:

public static async Task Test()
{
    Task pending = Task.FromResult(true);
    try
    {
        pending = SendAsync1();
    }
    catch (Exception)
    {
        Console.WriteLine("1-sync");
    }

    try
    {
        await pending;
    }
    catch (Exception)
    {
        Console.WriteLine("1-async");
    }

    pending = Task.FromResult(true);
    try
    {
        pending = SendAsync2();
    }
    catch (Exception)
    {
        Console.WriteLine("2-sync");
    }

    try
    {
        await pending;
    }
    catch (Exception)
    {
        Console.WriteLine("2-async");
    }
}

public static async Task SendAsync1()
{
    throw new Exception("Sync Exception");
    await Task.Delay(10);
}

public static Task SendAsync2()
{
    throw new Exception("Sync Exception");
    return Task.Delay(10);
}

Output:

1-async
2-sync
like image 61
i3arnon Avatar answered Oct 16 '22 18:10

i3arnon