2015-08-20 3 views
3

Возьмите этот async метод:Tail вызов асинхронной без ждать

public async Task<string> ReadStringFromUrlAsync(string url) 
{ 
    WebRequest request = WebRequest.Create(url); 
    WebResponse response = request.GetResponse(); 
    Stream dataStream = response.GetResponseStream(); 
    var reader = new StreamReader(dataStream); 
    return await reader.ReadToEndAsync(); 
} 

Поскольку он возвращает результат другой задачи, я считаю, я могу избавиться от async и await:

public Task<string> ReadStringFromUrlAsync(string url) 
{ 
    WebRequest request = WebRequest.Create(url); 
    WebResponse response = request.GetResponse(); 
    Stream dataStream = response.GetResponseStream(); 
    var reader = new StreamReader(dataStream); 
    return reader.ReadToEndAsync(); 
} 

Я заметил, что стек вызовов в случае исключения не укажет ReadStringFromUrlAsync, есть ли какие-либо другие недостатки для удаления aysnc/await на хвостовых вызовах таким образом.

+1

Как написано это нормально, но вы забыли распоряжаться этими ресурсами , Теперь вам нужно еще раз подождать. – usr

+0

Хороший вопрос, я пришел к такому выводу давно, когда увидел, что в нашей базе кода есть избыточное ожидание. –

+0

@usr спасибо за это, это метод, который я рефакторинг для 'async', и это полностью ускользнуло мое внимание. Это плохой пример для вопроса. Я не буду редактировать, потому что ответы ссылаются на него. Я думаю, давайте просто предположим, что в случае, когда я спрашиваю, что нет ничего, что должно быть устранено. – weston

ответ

4

В большинстве случаев это нормально, но существует важная разница в поведении исключений: любые исключения до возвращенная задача будет выбрана непосредственно, а не помещена в задание. В вашем примере, если WebRequest.Create, GetResponse, GetResponseStream или StreamReader(..) выбрасывает, то в методе async исключение будет помещено в задачу, а в методе не async исключение будет выбрано напрямую.

Кстати, если это представитель вашего реального кода, я бы рекомендовал использовать HttpClient вместо этого, который был разработан с await в виду:

public Task<string> ReadStringFromUrlAsync(string url) 
{ 
    return new HttpClient().GetStringAsync(url); 
} 
+0

Спасибо, да, это точный метод из кода, я не писал его изначально, но был рефакторинг 'async'. Вид моего внимания о том, что в моем коде нет распоряжения. Определенно изменится на 'HttpClient', но с блоком' using' вы не думаете? Как [эти примеры] (http://www.asp.net/web-api/overview/advanced/calling-a-web-api-from-a-net-client). И как только у меня будет блок 'using', мне нужно будет снова использовать' async'/'await'? – weston

+0

@weston: Если вы используете блок 'using', то да. Но большинство реального использования «HttpClient» кэширует экземпляр. Один экземпляр «HttpClient» способен на любое количество одновременных асинхронных вызовов. –

2

Все должно быть в порядке с удаления await и async. На самом деле, команда Roslyn (новый компилятор C#) думает о том, чтобы сделать ее компилятором optimization.

1

Да, это правильно. Когда вы просто возвращаете задание, вы можете просто опустить async и сразу вернуть Task, без await ing.

Смежные вопросы