Мне звонят из C#
приложения метро на базе xaml на Win8 CP; этот вызов просто попадает в веб-службу и возвращает данные JSON.
HttpMessageHandler handler = new HttpClientHandler();
HttpClient httpClient = new HttpClient(handler);
httpClient.BaseAddress = new Uri("http://192.168.1.101/api/");
var result = await httpClient.GetStreamAsync("weeklyplan");
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(WeeklyPlanData[]));
return (WeeklyPlanData[])ser.ReadObject(result);
Он зависает, await
но http- вызов фактически возвращается почти сразу (подтверждено скриптом); это как будто await
игнорируется и просто висит там.
Прежде чем вы спросите - ДА - возможность частной сети включена.
Есть идеи, почему это зависло?
c#
asynchronous
async-await
dotnet-httpclient
keithwarren7
источник
источник
async
метод? Разве это не вызывает исключение?Ответы:
Посмотрите этот ответ на мой вопрос, который кажется очень похожим.
Что можно попробовать: вызовите
ConfigureAwait(false)
Задачу, возвращеннуюGetStreamAsync()
. НапримерПолезно это или нет, зависит от того, как вызывается приведенный выше код - в моем случае вызов
async
метода usingTask.GetAwaiter().GetResult()
привел к зависанию кода.Это связано с тем,
GetResult()
что текущий поток блокируется до завершения задачи. Когда задача завершается, она пытается повторно войти в контекст потока, в котором она была запущена, но не может, потому что в этом контексте уже есть поток, который заблокирован вызовомGetResult()
... взаимоблокировки!В этом сообщении MSDN подробно рассказывается о том, как .NET синхронизирует параллельные потоки, а ответ на мой собственный вопрос дает некоторые передовые практики.
источник
Просто предупреждаем - если вы пропустите ожидание на верхнем уровне в контроллере ASP.NET и вернете задачу вместо результата в качестве ответа, она фактически просто зависнет во вложенных вызовах ожидания без ошибок. Глупая ошибка, но если бы я увидел этот пост, это могло бы сэкономить мне время, проверяя код на предмет чего-то странного.
источник
Отказ от ответственности: мне не нравится решение ConfigureAwait (), потому что я считаю его неинтуитивным и трудным для запоминания. Вместо этого я пришел к заключению, что вызовы не ожидаемых методов следует переносить в Task.Run (() => myAsyncMethodNotUsingAwait ()). Кажется, это работает на 100%, но может быть просто состоянием гонки !? Я не уверен, что происходит, если честно. Этот вывод может быть неверным, и я рискую своими очками StackOverflow здесь, чтобы, надеюсь, извлечь уроки из комментариев :-P. Пожалуйста, прочтите их!
У меня была проблема, как описано, и я нашел здесь дополнительную информацию .
Утверждение: «вы не можете вызвать асинхронный метод».
из метода, который блокирует
В моем случае я не мог изменить метод вызова, и он не был асинхронным. Но на самом деле результат меня не волновал. Насколько я помню, также не сработало удаление .Result и отсутствие ожидания.
Итак, я сделал это:
В моем случае меня не волновал результат вызова неасинхронного метода, но я предполагаю, что это довольно часто встречается в этом случае использования. Вы можете использовать результат в вызывающем методе async.
источник