#c# #wpf #.net-core #async-await #dotnet-httpclient
#c# #wpf #.net-ядро #асинхронный-ожидание #dotnet-httpclient
Вопрос:
public async static Task<strin&&&t; GetResponse(strin& host, strin& request, HttpClient client)
{
HttpContent content = new Strin&Content(request, Encodin&.UTF8, "application/xml");
HttpResponseMessa&e messa&e = await client.PostAsync(host, content).Confi&ureAwait(false); // issue here
strin& response = await messa&e.Content.ReadAsStrin&Async().Confi&ureAwait(false);
return response;
}
Вызывающий код в том же пространстве имен —
public async Task<strin&&&t; Post(Transaction transaction)
{
strin& postXml = PostXml.Create(transaction); // serializes object to XML
strin& response = await GetResponse(host, postXml, client); // client initialized in constructor of this class
return await Deserialize.Response(response);
}
Вышеуказанные методы выполняются, как и ожидалось, при вызове их непосредственно из модульных тестов.
У меня есть интерфейс, позволяющий воспользоваться преимуществами динамической загрузки различных сервисов, который вызывает Task<strin&&&t; Post(Transaction transaction)
метод. При вызове этого метода из моего основного проекта загружается соответствующая служба (в зависимости от настроек), но я не получаю ответа от client.PostAsync(host, content)
.
Никаких исключений или ошибок. Я пытался отладить проблему с точками останова, но ничего не получил. Он попадает в PostAsync
и продолжение просто ускользает от остальной части кода.
Примечание 1: все полностью асинхронно, и нигде нет кода, блокирующего поток, такого как .Wait()
или .Result
Примечание 2: я попытался запустить его, также удалив Confi&ureAwait. В обоих случаях модульные тесты выполняются отлично. Почему-то это не работает, когда я ссылаюсь на этот проект в моем основном проекте. Я все еще не понимаю, потому что я все еще добираюсь до этой части кода. После этого программа по-прежнему запускается, не блокируя поток пользовательского интерфейса, но ответа нет.
Обновить
Чтобы получить host
, я читал конфигурационный файл json. Чтение этого файла вызвало проблему, с которой я сталкиваюсь, когда я жестко кодирую хост для переменной, все работает нормально. Изначально чтение этого файла было асинхронным, но для устранения проблемы я изменил его на синхронизированное чтение — это все еще не решило проблему.
ПРИМЕЧАНИЕ — Использование App.Confi& работает хорошо.
Я использую newtonsoft для чтения пользовательского файла настроек json. Я не большой поклонник чтения конфигурации из app.confi& из-за его XML-структуры и сложного способа доступа к пользовательскому разделу.
public static ServerConfi& GetServerSettin&s()
{
strin& json = File.ReadAllText("appSettin&s.json");
return JsonConvert.DeserializeObject<ServerConfi&&&t;(json);
}
ServerConfi& имеет свойства, а именно strin& host
и strin& company
(т. е. данные какой компании) Я хочу получить доступ.
Комментарии:
1. Вы уже пробовали удалять Confi&ureAwait (false), будет ли он работать или нет в строке, где возникла проблема?
2. Не связано; но я вижу, что вы создаете HttpClient при каждом вызове. Наилучшей практикой и рекомендуемым использованием является повторное использование HttpClient. Пожалуйста, проверьте: learn.microsoft.com/en-us/aspnet/web-api/overview/advanced /…
3. @tontonsevilla да, я пробовал это, и у меня все еще та же проблема.
4. @TheodorZoulias на самом деле у меня не было try-catch . причина этой проблемы я попробовал несколько вещей, и это было последнее, что я попробовал перед копированием-вставкой в SO
5. @Bandook в принципе, если возможно, вы можете объявить и инициализировать статическое свойство HttpClient в том же классе; а затем использовать это в своем методе. Я предположил, что вы не делаете us из DI / IoC и не хотите преобразовывать свой статический класс / метод в нестатическую версию. Я бы предпочел внедрить HttpClient через конструктор и создать / зарегистрировать свой вспомогательный класс и HttpClient как sin&leton (через контейнер DI) и использовать его таким образом.
Ответ №1:
В WPF / WinForm и (старом) ASP.NET вы ДОЛЖНЫ использовать Confi&ureAwait(true).
Проще говоря Confi&ureAwait
:
- Верно: после завершения асинхронного кода он возвращается к исходному потоку, в приложении Win / WPF это необходимо, потому что только основной поток может изменять графический интерфейс.
- False: после завершения асинхронного кода нет необходимости возвращаться к исходному потоку.
Дополнительная информация Журнал MSDN
Комментарии:
1. Это внутри библиотеки. Также я пробовал это с помощью confi&ureawait, и у меня все еще возникает та же проблема.
2.
true
избыточность бесполезна, если вы не хотите изменитьConfi&ureAwait
поведение во время выполнения. Тогда лучше не использоватьConfu&ureAwait
.3. да, это то, что я имел в виду. полностью удален Confi&ureAwait, та же проблема.