Что не так с этой асинхронностью?

#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 Основной метод должен возвращать a Task .

3. @PetNoire то, что руководство Вы читаете: — это очень-очень неправильно, .Wait() отменяет все, что async пытается достигнуть — и вводит в тупик риска, в некоторых случаях, как дополнительный пинок под зад, а как ждать его до конца: это именно то, что await делает (но: вместо того, чтобы блокировать текущий поток, он использует асинхронный обратный вызов шаблона при необходимости)

4. но мне нужно, чтобы он заблокировался. и пустая задача не является частью проблемы. если HttpClient. GetAsync().Wait () — буквально единственная строка во всем коде, она зависает, и я не могу найти ничего другого, что позволило бы мне дождаться ее завершения

5. @PetNoire что заставляет вас думать, что вы должны блокировать, вместо того, чтобы использовать async/await? Обратите внимание, что HttpClient восстановил некоторые методы синхронизации в последних обновлениях, но асинхронность по-прежнему предпочтительнее