Чи безпечно HttpClient одночасно використовувати?


151

У всіх прикладах, з яких я можу знайти звичаї HttpClient, він використовується для разових дзвінків. Але що робити, якщо у мене стійка ситуація з клієнтом, коли одночасно можна зробити кілька запитів? В основному, чи безпечно дзвонити client.PostAsyncпо 2 потоку одразу проти того ж екземпляра HttpClient.

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


2
Також читайте це питання для отримання додаткової інформації про те , як правильно використовувати HttpClientі розпоряджатися нею: stackoverflow.com/questions/15705092 / ...
Mani Gandham

Відповіді:


152

Згідно з MSDN , оскільки .NET 4.5 Наступні методи екземпляра безпечні для потоків (спасибі @ischell):

CancelPendingRequests
DeleteAsync
GetAsync
GetByteArrayAsync
GetStreamAsync
GetStringAsync
PostAsync
PutAsync
SendAsync

3
Так, я не був впевнений у цьому, оскільки, здається, це стандартне попередження про все на MSDN (і я пам'ятаю, як читав деякі блоги MSDN про те, як колись це попередження неправильне, оскільки воно застосовується наосліп до всього).
Алекс К

3
Це неправильно; У розділі зауважень на сторінці MSDN, яку ви пов’язали, йдеться про те, що GetAsync, PostAsync тощо є безпечними для потоків.
ischell

4
@ischell: Я можу запевнити, що під час обговорення цього питання цього пункту ще не було.
Марсель Н.

7
Отже, Microsoft сконструювала HttpClient для багаторазового використання, але тоді клас має дані екземпляра для заголовків: client.DefaultRequestHeaders.Accept.Add (...);
cwills

8
Наприкінці, але я хотів прокоментувати @cwills. ТиповоRequestHeaders - це саме те, за замовчуванням. Якщо вам потрібні різні заголовки на основі запиту, ви можете створити новий StringContent (), встановити додаткові заголовки для цього, а потім використовувати перевантаження, яке сприймає URI та HttpContent.
Райан Андерсон

92

Ось ще одна стаття Генріка Ф. Нільсена про HttpClient, де він говорить:

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


13
Що робити, якщо ім’я користувача та пароль можуть змінюватися між потоками? це те, що я, здається, не можу знайти, щоб про когось говорили
Nicholas DiPiazza

1
@NicholasDiPiazza: як часто це змінюється? Якщо є відомий набір користувачів / паролів, ви можете створити пул екземплярів HttpClient.
Марсель Н.

Так, саме так я і закінчився
Ніколас ДіПіацца

2
Зауважте, що повторне використання того ж HttpClient для всіх ваших запитів може призвести до несвіжих проблем DNS: github.com/dotnet/corefx/isissue/11224 .
Охад Шнайдер

1
@OhadSchneider Якщо вважаєте, що проблема обмежена ядром .net Виправити проблему можна .net 4, вставивши в конструктор HttpClient спеціальний HttpClientHandler, встановивши "ConnectionLeaseTimeout". Однак якщо протягом 100 секунд жодних запитів не надсилається до кінцевої точки, з’єднання оновиться самостійно. Захищене перезапис Завдання <HttpResponseMessage> SendAsync (HttpRequestMessage запит, СкасуванняЗайнято скасуванняToken) {var sp = ServicePointManager.FindServicePoint (request.RequestUri); sp.ConnectionLeaseTimeout = 100 * 1000; }
Тимофій Гонсалес

17

Знайдено одне повідомлення на форумі MSDN Генріка Ф. Нільсена (одного з головних архітекторів HttpClient).

Швидкий підсумок:

  • Якщо у вас є запити, які пов'язані (або не наступатимуть на будь-який інший), то використання того ж HttpClient має багато сенсу.
  • У загальному плані я рекомендував би максимально використовувати екземпляри HttpClient.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.