Apakah HttpClient aman untuk digunakan secara bersamaan?

151

Dalam semua contoh yang dapat saya temukan tentang penggunaan HttpClient, digunakan untuk satu panggilan. Tetapi bagaimana jika saya memiliki situasi klien yang persisten, di mana beberapa permintaan dapat dibuat secara bersamaan? Pada dasarnya, apakah aman untuk memanggil client.PostAsync2 utas sekaligus terhadap instance yang sama HttpClient.

Saya tidak benar-benar mencari hasil eksperimen di sini. Sebagai contoh yang berfungsi bisa saja kebetulan (dan terus-menerus pada saat itu), dan contoh yang gagal dapat menjadi masalah kesalahan konfigurasi. Idealnya saya mencari jawaban otoritatif untuk pertanyaan penanganan konkurensi di HttpClient.

Alex K
sumber
2
Baca juga pertanyaan ini untuk info lebih lanjut tentang cara menggunakan HttpClientdan membuangnya dengan benar: stackoverflow.com/questions/15705092/…
Mani Gandham

Jawaban:

152

Menurut MSDN , sejak .NET 4.5 Metode contoh berikut aman untuk thread (terima kasih @ischell):

CancelPendingRequests
DeleteAsync
GetAsync
GetByteArrayAsync
GetStreamAsync
GetStringAsync
PostAsync
PutAsync
SendAsync
Marcel N.
sumber
3
Ya, saya tidak yakin tentang yang itu, karena tampaknya menjadi peringatan standar pada semua yang ada di MSDN (dan saya ingat membaca beberapa blog MSDN tentang bagaimana kadang-kadang peringatan itu salah, karena diterapkan secara membabi buta pada semuanya).
Alex K
3
Ini salah; di bagian komentar pada halaman MSDN yang Anda tautkan, dikatakan bahwa GetAsync, PostAsync, dll. semuanya aman.
Ischell
4
@ischell: Saya dapat meyakinkan Anda bahwa paragraf yang dimaksud tidak ada pada saat masalah ini dibahas.
Marcel N.
7
Jadi Microsoft telah merancang HttpClient agar dapat digunakan kembali tetapi kemudian kelas memiliki data contoh untuk header: client.DefaultRequestHeaders.Accept.Add (...);
cwills
8
Pada akhir, tapi saya ingin berkomentar di @cwills. DefaultRequestHeaders hanya itu, default. Jika Anda ingin tajuk yang berbeda berdasarkan permintaan, Anda dapat membuat StringContent baru (), atur tajuk tambahan itu, lalu gunakan overload yang mengambil URI dan HttpContent.
Ryan Anderson
92

Berikut ini artikel lain dari Henrik F. Nielsen tentang HttpClient di mana ia berkata:

" HttpClient default adalah cara paling sederhana di mana Anda dapat mulai mengirim permintaan. HttpClient tunggal dapat digunakan untuk mengirim sebanyak permintaan HTTP yang Anda inginkan secara bersamaan sehingga dalam banyak skenario Anda hanya dapat membuat satu HttpClient dan kemudian menggunakannya untuk semua permintaan Anda . "

muruge
sumber
13
Bagaimana jika nama pengguna dan kata sandi dapat berubah di antara utas? itulah yang sepertinya tidak bisa saya temukan yang dibicarakan orang
Nicholas DiPiazza
1
@NicholasDiPiazza: seberapa sering itu berubah? Jika ada satu set pasangan pengguna / kata sandi yang dikenal maka Anda dapat membuat kumpulan instance HttpClient.
Marcel N.
ya itulah yang akhirnya saya lakukan
Nicholas DiPiazza
2
Perhatikan bahwa menggunakan kembali HttpClient yang sama untuk semua permintaan Anda dapat menyebabkan masalah DNS basi: github.com/dotnet/corefx/issues/11224 .
Ohad Schneider
1
@OhadSchneider Jika yakin bahwa masalah ini terbatas pada .net core. Anda dapat memperbaiki masalah dengan .net 4 dengan menyuntikkan HttpClientHandler kustom ke konstruktor HttpClient kemudian mengatur "ConnectionLeaseTimeout". Namun, jika tidak ada permintaan yang dikirim ke titik akhir selama 100 detik koneksi akan menyegarkan dengan sendirinya. protected override Task <HttpResponseMessage> SendAsync (HttpRequestMessage request, PembatalanToken cancellationToken) {var sp = ServicePointManager.FindServicePoint (request.RequestUri); sp.ConnectionLeaseTimeout = 100 * 1000; }
Timothy Gonzalez
17

Ditemukan satu posting forum MSDN oleh Henrik F. Nielsen (salah satu Arsitek utama HttpClient).

Ringkasan cepat:

  • Jika Anda memiliki permintaan yang terkait (atau tidak mau saling menginjak) maka menggunakan HttpClient yang sama masuk akal.
  • Secara umum saya akan merekomendasikan menggunakan kembali contoh HttpClient sebanyak mungkin.
Alex K
sumber