Безопасно ли использовать HttpClient одновременно?

Во всех примерах использования HttpClient, которые я могу найти, он используется для одноразовых вызовов. Но что, если у меня постоянная клиентская ситуация, когда несколько запросов могут выполняться одновременно? В принципе, безопасно ли вызывать client.PostAsync в двух потоках одновременно для одного и того же экземпляра HttpClient.

Я не ищу здесь экспериментальных результатов. В качестве рабочего примера может быть просто случайность (причем постоянная), а неудачный пример может быть проблемой неправильной конфигурации. В идеале я ищу авторитетный ответ на вопрос об обработке параллелизма в HttpClient.


person Alex K    schedule 24.06.2012    source источник
comment
Также прочтите этот вопрос для получения дополнительной информации о том, как правильно использовать HttpClient и избавиться от него: stackoverflow.com/questions/15705092/   -  person Mani Gandham    schedule 03.07.2016


Ответы (3)


Согласно Microsoft Docs, поскольку .NET 4.5 Следующие методы экземпляра потокобезопасны (спасибо @ischell):

CancelPendingRequests
DeleteAsync
GetAsync
GetByteArrayAsync
GetStreamAsync
GetStringAsync
PostAsync
PutAsync
SendAsync
PatchAsync
person Marcel N.    schedule 24.06.2012
comment
Да, я не был уверен насчет этого, так как это похоже на стандартное предупреждение обо всем на MSDN (и я помню, как читал некоторые блоги MSDN о том, как иногда это предупреждение является неправильным, поскольку оно применяется вслепую ко всему). - person Alex K; 24.06.2012
comment
@AlexK: Ну, я бы не поверил всему, что слышу. Взгляните на это: msdn.microsoft.com/en-us/library /dd287191.aspx. Итак, я бы в целом доверял MSDN. - person Marcel N.; 24.06.2012
comment
Что ж, блоги тоже есть на MSDN, это загадка :) В любом случае, я думаю, что ошибусь в плане осторожности и буду использовать стратегию «клиент по запросу». - person Alex K; 24.06.2012
comment
С другой стороны, HttpClient имеет CancelPendingRequests, который отменяет все ожидающие запросы в этом экземпляре. - это, кажется, предполагает, что у него может быть несколько запросов в полете. - person friism; 09.07.2012
comment
Это не правильно; в разделе примечаний на странице MSDN, которую вы связали, говорится, что GetAsync, PostAsync и т. д. являются потокобезопасными. - person ischell; 04.01.2013
comment
@ischell: Могу вас заверить, что рассматриваемого абзаца не было в то время, когда обсуждалась эта проблема. - person Marcel N.; 04.01.2013
comment
К вашему сведению, он по-прежнему говорит, что методы экземпляра не являются потокобезопасными в нижней части страницы MSDN. - person Matt; 16.10.2013
comment
@Matt: Это было всегда, и это общее замечание о безопасности потоков для всех типов .NET. См. Раздел «Примечания» выше в статье MSDN. - person Marcel N.; 16.10.2013
comment
Итак, Microsoft разработала HttpClient для многократного использования, но тогда у класса есть данные экземпляра для заголовков: client.DefaultRequestHeaders.Accept.Add (...); - person cwills; 11.06.2014
comment
Я не уверен, что HttpClient ориентирован на многопоточность. Здесь есть 2 сценария: 1. Вызов client.GetAsync (), ожидание, пока он вернет объект Task, а затем его повторный вызов (в любом потоке) - все должно быть в порядке - параллелизма с нашими вызовами нет. HttpClient обрабатывает запрос в фоновом режиме и завершает каждую задачу после выполнения запроса, или 2. Вызов client.GetAsync () несколько раз в нескольких потоках, не дожидаясь, пока объект Task будет возвращен каждый раз. Это параллелизм, и я сомневаюсь, что он поддерживается из коробки. Не гарантируется, что асинхронные методы обеспечивают безопасность потоков (случай № 2). - person Alec Bryte; 02.06.2015
comment
Поздно, но я хотел прокомментировать @cwills. DefaultRequestHeaders - это просто значения по умолчанию. Если вам нужны разные заголовки для каждого запроса, вы можете создать новый StringContent (), установить для него дополнительные заголовки, а затем использовать перегрузку, которая принимает URI и HttpContent. - person Ryan Anderson; 21.11.2017
comment
HttpClient также имеет максимальное количество подключений по умолчанию на сервер (HttpClientHandler.MaxConnectionsPerServer), равное всего 2. Убедитесь, что вы увеличили это значение, иначе ваши многопоточные запросы просто заблокируются. - person PerpetualStudent; 15.06.2018
comment
Кроме того, чтобы установить разные Uri и заголовки для потоковых запросов, вы можете использовать HttpRequestMessage и передать его, например, SendAsync. - person PerpetualStudent; 15.06.2018
comment
Кто-нибудь знает, безопасно ли использовать этот одноэлементный шаблон для HttpClient на стороне сервера в приложении, которое будет иметь несколько пользователей? - person Chucky; 25.02.2019

Вот еще одна статья из Хенрик Ф. Нильсен о HttpClient говорит:

"HttpClient по умолчанию - это самый простой способ начать отправку запросов. Один HttpClient можно использовать для одновременной отправки любого количества HTTP-запросов, поэтому во многих сценариях вы можете просто создать один HttpClient, а затем использовать его для всех ваших запросов. "

person muruge    schedule 15.11.2012
comment
Что насчет того, если имя пользователя и пароль могут меняться между потоками? это то, о чем я не могу найти, чтобы кто-нибудь говорил о - person Nicholas DiPiazza; 05.11.2016
comment
@NicholasDiPiazza: как часто он меняется? Если существует известный набор пар пользователь / пароль, вы можете создать пул экземпляров HttpClient. - person Marcel N.; 23.06.2017
comment
да, вот что я в итоге сделал - person Nicholas DiPiazza; 23.06.2017
comment
Обратите внимание, что повторное использование одного и того же HttpClient для всех ваших запросов может привести к устаревшим проблемам DNS: github.com/dotnet / corefx / issues / 11224. - person Ohad Schneider; 07.07.2017
comment
@OhadSchneider Если вы считаете, что проблема ограничена ядром .NET. Вы можете решить проблему с .net 4, внедрив пользовательский HttpClientHandler в конструктор HttpClient, а затем установив ConnectionLeaseTimeout. Однако, если в конечную точку не отправляются запросы в течение 100 секунд, соединение обновится само. защищенная задача переопределения ‹HttpResponseMessage› SendAsync (запрос HttpRequestMessage, токен отмены отмены) {var sp = ServicePointManager.FindServicePoint (request.RequestUri); sp.ConnectionLeaseTimeout = 100 * 1000; } - person Timothy Gonzalez; 04.10.2017
comment
В чем смысл? Является ли HttpClient особенно дорогим, если не следует создавать новый для каждого запроса? - person xr280xr; 07.04.2021
comment
@ xr280xr простой ответ: да, его утилизация быстро истощит ваши TCP-сокеты под нагрузкой. Длинный ответ: это сложно, и никто не знает, как правильно его использовать. https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/ stackoverflow.com/a/15708633/825588 https://www.nimaara.com/beware-of-the-net-httpclient/ docs.microsoft.com/en-us/azure/architecture/antipatterns/ - person Johann; 22.04.2021
comment

Найдено одно сообщение на форуме MSDN Хенрика Ф. Нильсена (одного из главных архитекторов HttpClient).

Краткое резюме:

  • # P3 #
  • # P4 #
person Alex K    schedule 25.06.2012