Partiye geç kaldım, ama işte bu zor konuyla ilgili öğrenme yolculuğum.
1. HttpClient'i tekrar kullanmakla ilgili resmi savunucuyu nerede bulabiliriz?
Demek istediğim, eğer HttpClient'i yeniden kullanmak amaçlanıyorsa
ve bunu yapmak önemliyse , bu tür bir savunucu birçok "Gelişmiş Konular", "Performans (anti) modeli" veya diğer blog yayınlarında saklanmak yerine, kendi API dokümantasyonunda daha iyi belgelenmiştir. . Aksi halde, yeni bir öğrencinin çok geç olmadan nasıl bilmesi gerekiyor?
Şu andan itibaren (Mayıs 2018), "c # httpclient" googlingi yapıldığında ilk arama sonucu , bu niyetten hiç bahsetmeyen MSDN'deki bu API referans sayfasına işaret ediyor . Yeni başlayanlar için buradaki 1. derste, MSDN yardım sayfası başlığından hemen sonra "Diğer Sürümler" bağlantısını tıklayın. Muhtemelen orada "mevcut sürümün" bağlantılarını bulacaksınız. Bu HttpClient durumunda, sizi bu niyet tanımını içeren en son belgeye götürecektir
.
Bu konuda yeni olan birçok geliştiricinin de doğru dokümantasyon sayfasını bulamadığından şüpheliyim, bu bilgi yaygın bir şekilde yayılmıyor ve insanlar daha sonra , muhtemelen zor bir şekilde bulduğunda şaşırdı
.
2. (yanlış?) Anlayışı using
IDisposable
Bu seferki biraz konu kapalı ama nasıl suçlayarak bu anılan blog yayınlarında insanları görmek için bir tesadüf değil, işaret hala değer HttpClient
'ın IDisposable
onları kullanma eğiliminde yapar arayüz using (var client = new HttpClient()) {...}
desen ve ardından soruna neden olmaktadır.
Bunun söylenmemiş (yanlış?) Bir anlayışa dayandığına inanıyorum:
“yeniden kullanılabilir bir nesnenin kısa ömürlü olması bekleniyor” .
NASIL, bu tarzda kod yazarken kesinlikle kısa süreli bir şeye benziyor olsa da:
using (var foo = new SomeDisposableObject())
{
...
}
IDisposal resmi belgeler
asla bahseder IDisposable
nesneler kısa ömürlü olmak zorunda. Tanım gereği, IDisposable yalnızca yönetilmeyen kaynakları serbest bırakmanıza izin veren bir mekanizmadır. Daha fazlası değil. Bu anlamda, sonunda elden çıkarmayı tetiklemek için BEKLENİRSİNİZ, ancak bunu kısa ömürlü bir şekilde yapmanız gerekmez.
Bu nedenle, elden çıkarmanın ne zaman tetikleneceğini doğru bir şekilde seçmek, gerçek nesnenin yaşam döngüsü gereksinimini temel almak sizin işinizdir. Sizi uzun ömürlü bir şekilde kullanılamaz bir ID kullanmanızdan alıkoyacak hiçbir şey yoktur:
using System;
namespace HelloWorld
{
class Hello
{
static void Main()
{
Console.WriteLine("Hello World!");
using (var client = new HttpClient())
{
for (...) { ... } // A really long loop
// Or you may even somehow start a daemon here
}
// Keep the console window open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
}
Bu yeni anlayışla, şimdi blog gönderisini tekrar görüyoruz, "düzeltmenin" bir HttpClient
kez başlatıldığını ama hiçbir zaman elden çıkarmadığını açıkça görebiliyoruz, bu yüzden netstat çıktısından görebiliyoruz ki bağlantı ESTABLISHED durumunda kaldı. Doğru kapatılmadı. Kapatılsaydı, durumu TIME_WAIT'de olurdu. Uygulamada, tüm programınız sona erdikten sonra açık olan sadece bir bağlantıyı sızdırmak önemli değil ve blog posteri düzeltmeden sonra hala bir performans artışı görüyor; ama yine de, tanımlanabilir şekilde suçlamak ve imha etmemeyi seçmek kavramsal olarak yanlıştır.
3. HttpClient'i statik bir özelliğe mi, hatta bir singleton'a mı koymalıyız?
Önceki bölümün anlayışına dayanarak, bence buradaki cevap açıktır: "zorunlu değil". Gerçekten, bir HttpClient AND (ve sonunda ideal olarak) elden çıkardığınız sürece kodunuzu nasıl düzenlediğinize bağlıdır.
Çok komik bir şekilde, mevcut resmi belgenin Açıklamalar bölümündeki örnek bile
tam olarak doğru yapmıyor. İmha edilmeyecek statik bir HttpClient özelliği içeren bir "GoodController" sınıfını tanımlar; Bu da, Örnekler bölümündeki başka bir örnekte
vurguladığı şeye uymuyor: "Dispose'i çağırmanız gerekir ... bu yüzden uygulama kaynakları sızdırmaz".
Ve son olarak, singleton kendi zorlukları olmadan değildir.
“Kaç kişi küresel değişkenin iyi bir fikir olduğunu düşünüyor? Hiç kimse.
Kaç kişi singleton'ın iyi bir fikir olduğunu düşünüyor? Birkaç.
Ne oluyor? Singletons, sadece bir sürü küresel değişkendir. ”
- Bu ilham verici konuşmadan, “Global State and Singletons” dan alıntılandı.
PS: SqlConnection
Bu, şu anki soru-cevap ile ilgisiz, ancak muhtemelen bilmesi gereken bir şey. SqlConnection kullanım şekli farklıdır. Sen SqlConnection yeniden gerekmediğini onun bağlantı havuzu böyle daha iyi idare edecek, çünkü.
Fark, uygulama yaklaşımlarından kaynaklanmaktadır. Her HttpClient örneği, kendi bağlantı havuzunu kullanır ( buradan alıntılanır
); ama SqlConnection kendisine göre bir merkezi bağlantı havuzu tarafından yönetilen bu .
Ve hala SqlConnection'ı atmanız gerekiyor, HttpClient için yapmanız gerekenle aynı.