Вложенные методы async/wait
Я пишу библиотеку, которая обертывает вызов сторонней веб-службы и пытаюсь заставить библиотеку использовать новые функции async/await. Каково правильное использование ключевых слов async/wait в следующем примере?
public class MyApi
{
public Task<ApiResult> DoSomethingAsync()
{
return this.DoSomethingCore();
}
public async Task<ApiResult> DoSomethingElseAsync()
{
return await this.DoSomethingCore();
}
private async Task<ApiResult> DoSomethingCore()
{
var httpClient = new HttpClient();
var httpResponseMessage = await httpClient.GetAsync("some url");
var rawResultText = await httpResponseMessage.Content.ReadAsStringAsync();
return new ApiResult(rawResultText);
}
}
Чтобы мой вызывающий абонент ожидал метод DoSomethingAsync, должен ли этот метод также добавлять к нему ключевые слова async и ожидания? Или это нормально, потому что оно возвращает задачу? Есть ли лучший шаблон для такого рода вложенности?
Я думаю, что метод DoSomethingAsync - правильный способ пойти сюда, правильно ли? Я считаю, что DoSomethingElseAsync кажется неправильным подходом при создании библиотеки.
Ответы
Ответ 1
Любой Task
может быть ожидаем, независимо от того, откуда он пришел.
Я не уверен, почему DoSomethingAsync
просто вызывает DoSomethingCore
, так как DoSomethingAsync
может быть так же легко async
и использовать await
.
Существует также общее правило которое вы должны использовать ConfigureAwait(false)
в библиотечных методах.
Изменить: Если вам не нужно использовать await
, не делайте метод async
. async
добавит некоторые накладные расходы (отметьте Channel9 для Stephen Toub Zen видео Async Performance). Если вы можете просто вернуть Task
(например, DoSomethingAsync
), сделайте это так.
Ответ 2
Приведенная ниже формулировка является функциональной, но, вероятно, вызовет дополнительные накладные расходы (из-за наличия вторичного обратного вызова для дополнительного метода асинхронного/ожидаемого.)
public async Task<ApiResult> DoSomethingElseAsync()
{
return await this.DoSomethingCore();
}
Проще вернуть задачу непосредственно, так как вы всегда можете ожидать эту задачу в другом месте, не имея метода, реализованного как "async". Async/await очень похож на использование "yield return"; он использует некоторую магию компилятора для реализации "yielding", но самому перечислению все равно, как вы его реализуете. Точно так же призыв "ждать" не волнует, как ожидают работы, если это будет возможно.