O HttpClient é seguro para uso simultâneo?

151

Em todos os exemplos que posso encontrar de usos HttpClient, ele é usado para chamadas pontuais. Mas e se eu tiver uma situação persistente de cliente, em que várias solicitações possam ser feitas simultaneamente? Basicamente, é seguro chamar client.PostAsync2 threads de uma só vez na mesma instância de HttpClient.

Não estou realmente procurando resultados experimentais aqui. Como um exemplo de trabalho, pode ser simplesmente um acaso (e persistente), e um exemplo com falha pode ser um problema de configuração incorreta. Idealmente, estou procurando uma resposta oficial para a questão do tratamento de simultaneidade no HttpClient.

Alex K
fonte
2
Leia também esta questão para mais informações sobre como usar corretamente HttpCliente descartá-la: stackoverflow.com/questions/15705092/...
Mani Gandham

Respostas:

152

De acordo com o MSDN , desde o .NET 4.5 Os seguintes métodos de instância são seguros para threads (obrigado @ischell):

CancelPendingRequests
DeleteAsync
GetAsync
GetByteArrayAsync
GetStreamAsync
GetStringAsync
PostAsync
PutAsync
SendAsync
Marcel N.
fonte
3
Sim, eu não tinha certeza sobre isso, pois parece ser um aviso padrão em tudo no MSDN (e lembro-me de ler alguns blogs do MSDN sobre como algum dia esse aviso está errado, pois é aplicado às cegas em tudo).
Alex K
3
Isto está errado; na seção de comentários da página do MSDN que você vinculou, diz que GetAsync, PostAsync etc. são todos seguros para threads.
Ischell
4
@ ischell: Posso garantir que o parágrafo em questão não estava lá no momento em que esta questão foi discutida.
Marcel N.
7
Portanto, a Microsoft projetou o HttpClient para ser reutilizável, mas a classe possui dados de instância para os cabeçalhos: client.DefaultRequestHeaders.Accept.Add (...);
cwills
8
No final, mas eu queria comentar no @cwills. DefaultRequestHeaders são exatamente isso, padrões. Se você deseja cabeçalhos diferentes por solicitação, pode criar um novo StringContent (), definir cabeçalhos adicionais e usar a sobrecarga que leva URI e HttpContent.
Ryan Anderson
92

Aqui está outro artigo de Henrik F. Nielsen sobre o HttpClient, onde ele diz:

" O HttpClient padrão é a maneira mais simples de começar a enviar solicitações. Um único HttpClient pode ser usado para enviar quantas solicitações HTTP você desejar simultaneamente. Em muitos cenários, você pode simplesmente criar um HttpClient e usá-lo para todas as suas solicitações. . "

muruge
fonte
13
E se o nome de usuário e a senha puderem mudar entre os threads? Isso é o que eu não consigo encontrar alguém falando
Nicholas DiPiazza
1
@NicholasDiPiazza: com que frequência isso muda? Se houver um conjunto conhecido de pares de usuário / senha, você poderá criar um pool de instâncias HttpClient.
Marcel N.
sim isso é o que eu acabei fazendo
Nicholas DiPiazza
2
Observe que a reutilização do mesmo HttpClient para todas as suas solicitações pode resultar em problemas antigos de DNS: github.com/dotnet/corefx/issues/11224 .
Ohad Schneider
1
@OhadSchneider Se acreditar que esse problema está limitado ao núcleo .net. Você pode corrigir o problema com o .net 4 injetando um HttpClientHandler personalizado no construtor HttpClient e definindo o "ConnectionLeaseTimeout". No entanto, se nenhuma solicitação for enviada ao terminal por 100 segundos, a conexão será atualizada por si própria. substituição protegida Tarefa <HttpResponseMessage> SendAsync (solicitação HttpRequestMessage, cancelamentoToken cancelamentoToken) {var sp = ServicePointManager.FindServicePoint (request.RequestUri); sp.ConnectionLeaseTimeout = 100 * 1000; }
Timothy Gonzalez
17

Foi encontrada uma postagem no fórum do MSDN de Henrik F. Nielsen (um dos principais arquitetos do HttpClient).

Resumo rápido:

  • Se você tiver solicitações relacionadas (ou que não se incomodam), usar o mesmo HttpClient faz muito sentido.
  • Em geral, eu recomendaria reutilizar as instâncias HttpClient o máximo possível.
Alex K
fonte