¿Es seguro usar HttpClient al mismo tiempo?


151

En todos los ejemplos que puedo encontrar de usos HttpClient, se usa para llamadas únicas. Pero, ¿qué sucede si tengo una situación persistente del cliente, en la que se pueden realizar varias solicitudes simultáneamente? Básicamente, ¿es seguro invocar client.PostAsync2 hilos a la vez contra la misma instancia de HttpClient.

Realmente no estoy buscando resultados experimentales aquí. Como ejemplo de trabajo, podría ser simplemente una casualidad (y persistente), y un ejemplo fallido puede ser un problema de configuración incorrecta. Idealmente, estoy buscando una respuesta autorizada a la cuestión del manejo de concurrencia en HttpClient.


2
Lea también esta pregunta para obtener más información sobre cómo usarla HttpClienty desecharla correctamente : stackoverflow.com/questions/15705092/…
Mani Gandham el

Respuestas:


152

Según MSDN , desde .NET 4.5 Los siguientes métodos de instancia son seguros para subprocesos (gracias @ischell):

CancelPendingRequests
DeleteAsync
GetAsync
GetByteArrayAsync
GetStreamAsync
GetStringAsync
PostAsync
PutAsync
SendAsync

3
Sí, no estaba seguro de eso, ya que parece ser una advertencia estándar sobre todo en MSDN (y recuerdo haber leído algunos blogs de MSDN acerca de cómo en algún momento esa advertencia es incorrecta, ya que se aplica a ciegas a todo).
Alex K

3
Esto está mal; en la sección de comentarios de la página de MSDN que vinculó, dice que GetAsync, PostAsync, etc. son todos seguros para subprocesos.
ischell

44
@ischell: Les puedo asegurar que el párrafo en cuestión no estaba allí cuando se discutió este tema.
Marcel N.

77
Por lo tanto, Microsoft ha diseñado HttpClient para que sea reutilizable, pero luego la clase tiene datos de instancia para encabezados: client.DefaultRequestHeaders.Accept.Add (...);
cwills

8
Al final, pero quería comentar en @cwills. DefaultRequestHeaders son solo eso, valores predeterminados. Si desea diferentes encabezados por solicitud, puede crear un nuevo StringContent (), establecer encabezados adicionales en eso, luego usar la sobrecarga que toma URI y HttpContent.
Ryan Anderson el

92

Aquí hay otro artículo de Henrik F. Nielsen sobre HttpClient donde dice:

" El HttpClient predeterminado es la forma más sencilla de comenzar a enviar solicitudes. Se puede usar un solo HttpClient para enviar tantas solicitudes HTTP como desee de forma simultánea, por lo que en muchos escenarios puede crear un HttpClient y luego usarlo para todas sus solicitudes " .


13
¿Qué pasa si el nombre de usuario y la contraseña pueden cambiar entre hilos? eso es lo que parece que no puedo encontrar a nadie hablando
Nicholas DiPiazza

1
@NicholasDiPiazza: ¿con qué frecuencia cambia? Si hay un conjunto conocido de pares de usuario / contraseña, puede crear un grupo de instancias HttpClient.
Marcel N.

Sí, eso es lo que terminé haciendo
Nicholas DiPiazza

2
Tenga en cuenta que la reutilización del mismo HttpClient para todas sus solicitudes puede provocar problemas de DNS obsoletos: github.com/dotnet/corefx/issues/11224 .
Ohad Schneider

1
@OhadSchneider Si cree que el problema está limitado a .net core. Puede solucionar el problema con .net 4 inyectando un HttpClientHandler personalizado en el constructor HttpClient y luego configurando "ConnectionLeaseTimeout". Sin embargo, si no se envían solicitudes al punto final durante 100 segundos, la conexión se actualizará por sí sola. Tarea de anulación protegida <HttpResponseMessage> SendAsync (solicitud HttpRequestMessage, CancellationToken cancellationToken) {var sp = ServicePointManager.FindServicePoint (request.RequestUri); sp.ConnectionLeaseTimeout = 100 * 1000; }
Timothy Gonzalez el

17

Encontré una publicación en el foro de MSDN por Henrik F. Nielsen (uno de los principales arquitectos de HttpClient).

Sumario rápido:

  • Si tiene solicitudes relacionadas (o que no se pisarán entre sí), usar el mismo HttpClient tiene mucho sentido.
  • En general, recomendaría reutilizar instancias HttpClient tanto como sea posible.
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.