C# Language Returning a Task without await


Example

Methods that perform asynchronous operations don't need to use await if:

  • There is only one asynchronous call inside the method
  • The asynchronous call is at the end of the method
  • Catching/handling exception that may happen within the Task is not necessary

Consider this method that returns a Task:

public async Task<User> GetUserAsync(int id)
{
    var lookupKey = "Users" + id;

    return await dataStore.GetByKeyAsync(lookupKey);
}

If GetByKeyAsync has the same signature as GetUserAsync (returning a Task<User>), the method can be simplified:

public Task<User> GetUserAsync(int id)
{
    var lookupKey = "Users" + id;

    return dataStore.GetByKeyAsync(lookupKey);
}

In this case, the method doesn't need to be marked async, even though it's preforming an asynchronous operation. The Task returned by GetByKeyAsync is passed directly to the calling method, where it will be awaited.

Important: Returning the Task instead of awaiting it, changes the exception behavior of the method, as it won't throw the exception inside the method which starts the task but in the method which awaits it.

public Task SaveAsync()
{
    try {
        return dataStore.SaveChangesAsync();
    }
    catch(Exception ex)
    {
        // this will never be called
        logger.LogException(ex);
    }
}

// Some other code calling SaveAsync()

// If exception happens, it will be thrown here, not inside SaveAsync()
await SaveAsync();

This will improve performance as it will save the compiler the generation of an extra async state machine.