Intereting Posts
Может ли пространство имен .NET содержать несколько сборок? Могу ли я использовать нулевой условный оператор вместо classического шаблона повышения событий? Получить сообщение об ошибке при использовании специального атрибута проверки Как вставить данные в коллекцию mongodb с помощью драйвера c # 2.0? Unity 2D C # Создавать спрайт на canvasе. Не могу найти, что не так WCF: PlatformNotSupportedException при запуске серверных проектов Получить идентификатор процесса клиента, подключенного к именованному серверу каналов с помощью C # Как получить случайный объект с помощью Linq Управление изображениями с помощью WPF VSTO 2012: обратная совместимость Код аварийного сигнала в Windows Phone 8.1 Смешивание пабы / суба с рабочими местами в RabbitMQ Чтение пар ключей в словаре из app.config configSection Преобразует ли NameValueCollection в querystring, используя ac # lambda эффективный? Самый простой способ редактировать коллекцию в DesignMode?

Тупик с использованием async & wait

То, что я хочу реализовать в своей программе, – это следующий столбец / рабочий процесс:

  1. отправка ()
  2. авторизации ()
  3. HttpPost ()

Моя идея состояла в том, что httpPost() будет асинхронным, а остальные 2 метода остаются несинхронными. Однако по какой-то причине это не сработало бы для меня, если бы я не сделал 2. + 3. asynchronous. Может быть, у меня все еще есть недоразумения.

Насколько я понимаю, я могу либо a) использовать await -keyword при вызове метода async (это приведет к приостановке метода и продолжению после завершения асинхронного метода), либо b) опустить await -keyword и вместо этого вызвать Task.Result async методы возвращают значение, которое будет блокироваться до тех пор, пока результат не будет доступен.


Позвольте мне показать вам рабочий пример:

  private int dispatch(string options) { int res = authorize(options).Result; return res; } static async private Task authorize(string options) { string values= getValuesFromOptions(options); KeyValuePair response = await httpPost(url, values); return 0; } public static async Task<KeyValuePair> httpPost(string url, List<KeyValuePair> parameters) { var httpClient = new HttpClient(new HttpClientHandler()); HttpResponseMessage response = await httpClient.PostAsync(url, new FormUrlEncodedContent(parameters)); int code = (int)response.StatusCode; response.EnsureSuccessStatusCode(); string responseString = await response.Content.ReadAsStringAsync(); return new KeyValuePair(code, responseString); } 

Позвольте мне показать вам нерабочий пример:

  private int dispatch(string options) { int res = authorize(options).Result; return res; } static private int authorize(string options) { string values= getValuesFromOptions(options); Task<KeyValuePair> response = httpPost(url, values); doSomethingWith(response.Result); // execution will hang here forever return 0; } public static async Task<KeyValuePair> httpPost(string url, List<KeyValuePair> parameters) { var httpClient = new HttpClient(new HttpClientHandler()); HttpResponseMessage response = await httpClient.PostAsync(url, new FormUrlEncodedContent(parameters)); int code = (int)response.StatusCode; response.EnsureSuccessStatusCode(); string responseString = await response.Content.ReadAsStringAsync(); return new KeyValuePair(code, responseString); } 

Я также попытался использовать все 3 метода не async и заменить await в httpPost на .Result s, но затем он будет вечно вешать в строке HttpResponseMessage response = httpClient.PostAsync(url, new FormUrlEncodedContent(parameters)).Result;

Может ли кто-нибудь просветить меня и объяснить, что моя ошибка?

У вас есть SynchronizationContext , и этот контекст захватывается, когда вы await так что продолжения (ы) могут выполняться в этом контексте.

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

Затем, прежде чем операция async будет завершена, у вас есть код в вашем основном контексте, который выполняет блокировку ожидания операции async. Продолжение невозможно запустить, потому что контекст занят, ожидая продолжения. Классический тупик.

Вот почему важно «асинхронно все», как это было в первом примере.

Есть несколько хаков, которые могут работать в тупике во втором примере, но это все еще не то, что вы должны делать. Весь asynchronous ход – избегать блокировки ваших streamов. Если вы просто продолжаете блокировать ожидание задачи, вы проиграете цель перехода асинхронно. Либо сделайте все асинхронным, либо ничего асинхронным, если у вас нет выбора.