Как правильно реализовать метод TAP?

Я хочу создать метод асинхронного шаблона на основе задач. При ожидании метода я не мог найти разницы между этими двумя способами предоставления метода:

// GetStats is a delegate for a void method in this example
public Task GetStatsAsync()
{
    return Task.Run(GetStats);
}

public async Task GetStatsAsync()
{
    return await Task.Run(GetStats);
}

// Usage:
await GetStatsAsync();
// Difference?

У верхнего метода, как представляется, меньше накладных расходов, чем нижний. Когда я смотрел блоги MSDN, я заметил, что они используют нижний метод. (Например, в в этой статье)

Почему? В чем же разница? Они оба работают.

Ответ 1

Оба логически одинаковы, но вторая имеет больше накладных расходов и не рекомендуется по этой причине.

Вы можете найти async intro help, а также асинхронный шаблонный документ.

Для получения дополнительной информации об издержках async, я рекомендую Zen of Async by Stephen Toub.

Вероятно, вы также захотите прочитать "Должен ли я предлагать асинхронные обертки для синхронных методов?" . Короче говоря, ответ "нет".

Ответ 2

У меня создалось впечатление, что правильным способом реализации шаблона TAP будет следующее:

  public Task<IResult> GetLongWindedTaskResult(){
          var tcs = new TaskCompletionSource<IResult>();
            try
            {
               tcs.SetResult(ResultOFSomeFunction());
            }
            catch (Exception exp)
            {
                tcs.SetException(exp);
            }
            return tcs.Task;
}

Этот способ гарантирует, что вы правильно получите исключение, если оно будет выбрано, и это облегчит реализацию метода отмены, если это необходимо.