В конце метода async я должен вернуться или подождать?

В конце метода async, возвращающего задачу, если я вызываю другой метод async, я мог бы либо await, либо return выполнить его задачу. Каковы последствия каждого?

    Task FooAsync()
    {
        return BazAsync();  // Option A
    }

    async Task BarAsync()
    {
        await BazAsync(); // Option B
    }

Ответ 1

Вы не можете вернуть задачу, если сам метод объявлен как async - поэтому это не сработает, например:

async Task BarAsync()
{
    return BazAsync(); // Invalid!
}

Для этого потребуется тип возврата Task<Task>.

Если ваш метод просто выполняет небольшую работу, а затем вызывает только один метод асинхронизации, тогда ваш первый вариант прекрасен и означает, что в нем задействовано еще меньше задач. Вы должны знать, что любые исключения, возникающие в вашем синхронном методе, будут передаваться синхронно, хотя, действительно, именно так я предпочитаю обрабатывать проверку аргументов.

Это также общий шаблон для реализации перегрузки, например. с помощью токена отмены.

Просто имейте в виду, что если вам нужно перейти на ожидание чего-то другого, вам нужно сделать вместо него метод async. Например:

// Version 1:
Task BarAsync()
{
    // No need to gronkle yet...
    return BazAsync();
}

// Oops, for version 2 I need to do some more work...
async Task BarAsync()
{
    int gronkle = await GronkleAsync();
    // Do something with gronkle

    // Now we have to await BazAsync as we're now in an async method
    await BazAsync();
}

Ответ 2

Посмотрите эту ссылку, где описано: http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx

async Task<int> TaskOfTResult_MethodAsync()
{
    int hours;
    // . . .
    // The body of the method should contain one or more await expressions.

    // Return statement specifies an integer result.
    return hours;
}

    // Calls to TaskOfTResult_MethodAsync from another async method.
private async void CallTaskTButton_Click(object sender, RoutedEventArgs e)
{
    Task<int> returnedTaskTResult = TaskOfTResult_MethodAsync();
    int intResult = await returnedTaskTResult;
    // or, in a single statement
    //int intResult = await TaskOfTResult_MethodAsync();
}






// Signature specifies Task
async Task Task_MethodAsync()
{
    // . . .
    // The body of the method should contain one or more await expressions.

    // The method has no return statement.  
}

    // Calls to Task_MethodAsync from another async method.
private async void CallTaskButton_Click(object sender, RoutedEventArgs e)
{
    Task returnedTask = Task_MethodAsync();
    await returnedTask;
    // or, in a single statement
    //await Task_MethodAsync();
}