#c# #asynchronous #async-await
Вопрос:
До сих пор мой опыт работы с асинхронными функциями шел довольно хорошо до того момента, когда мне действительно нужно дождаться завершения задачи. Этот код иногда вызывает сервер, в зависимости от того, попадает ли он туда до выхода приложения:
async void Main(string[] args) { await new HttpClient().GetAsync("http://localserver"); }
Этот код зависает на неопределенный срок и никогда не пингует сервер:
void Main(string[] args) { new HttpClient().GetAsync("http://localserver").Wait(); }
Кто-нибудь может это объяснить?
Комментарии:
1. Никакого упрека. На моем компьютере ваш код (с
Wait
) выдаетHttpRequestException: No such host is known. (localserver:80)
через несколько секунд (завернутый вAggregateException
).
Ответ №1:
Никогда .Wait()
не ожидаемый; всегда await
.
Там есть немного места для маневра в превосходной степени, но сценарии, в которых это имеет значение, являются нишевыми и не применимы к большинству кодов.
void
Метод с an await
непредсказуем именно потому , что вызывающий не может определить статус выполнения; в принципе: никогда (с той же оговоркой) используйте async void
: используйте async Task
и убедитесь, что вызывающий ожидает его.
Что касается того, почему он заблокирован: вероятно, тупик из-за контекста синхронизации в пользовательском интерфейсе. Если ни одно из этих слов не имеет смысла: не волнуйтесь, в этом нет необходимости, если вы просто используете await
вместо .Wait()
(Для ясности: все, о чем говорится .Wait()
, также относится к .Result
, .GetAwaiter().GetResult()
, или ко всему, что вы можете привести)
Комментарии:
1. так как же мне дождаться, когда это закончится? я никогда не видел, чтобы что-то упоминалось, но подождите’
2. «никогда … используйте
async void
«.async
Основной метод должен возвращать aTask
.3. @PetNoire то, что руководство Вы читаете: — это очень-очень неправильно,
.Wait()
отменяет все, что async пытается достигнуть — и вводит в тупик риска, в некоторых случаях, как дополнительный пинок под зад, а как ждать его до конца: это именно то, чтоawait
делает (но: вместо того, чтобы блокировать текущий поток, он использует асинхронный обратный вызов шаблона при необходимости)4. но мне нужно, чтобы он заблокировался. и пустая задача не является частью проблемы. если HttpClient. GetAsync().Wait () — буквально единственная строка во всем коде, она зависает, и я не могу найти ничего другого, что позволило бы мне дождаться ее завершения
5. @PetNoire что заставляет вас думать, что вы должны блокировать, вместо того, чтобы использовать async/await? Обратите внимание, что HttpClient восстановил некоторые методы синхронизации в последних обновлениях, но асинхронность по-прежнему предпочтительнее