Konuları okumak zorunda SqlCommand.Dispose yeterli mi? ve WCF Hizmetini Kapatma ve Atma SqlConnection gibi sınıfları veya Stream sınıfından miras alan birkaç sınıftan birini merak ediyorum Kapatmak yerine Dispose'i kapatmamın önemi var mı?
Konuları okumak zorunda SqlCommand.Dispose yeterli mi? ve WCF Hizmetini Kapatma ve Atma SqlConnection gibi sınıfları veya Stream sınıfından miras alan birkaç sınıftan birini merak ediyorum Kapatmak yerine Dispose'i kapatmamın önemi var mı?
Yanıtlar:
Microsoft yönergelerine göre, Closeuygun olan yerlerde yöntem sağlamak iyi bir uygulamadır . İşte Framework tasarım yönergelerinden bir alıntı
Yöntem sağlayarak göz önünde
Close()ek olarak,Dispose()kapalı alanda standart terminoloji ise. Bunu yaparken,Closeuygulamanın aynı olması önemlidirDispose...
Çoğu durumda Closeve Disposeyöntemler eşdeğerdir. Temel fark arasındaki Closeve Disposesöz konusu SqlConnectionObjectgeçerli:
Bir uygulama
Closebirden fazla kez çağırabilir . İstisna oluşturulmaz.Eğer
DisposeyöntemiSqlConnectionçağırdıysanız nesne durumu sıfırlanacaktır. AtılanSqlConnectionnesnede herhangi bir yöntemi çağırmayı denerseniz , istisna alırsınız.
Bahsedilen:
Dispose.Closeyöntemi kullanın .con.Open() con.Close(); 2 con.Open(); // reuse 3. con.Dispose(); // use one time con.Open(); // error
Her zamanki gibi cevap: duruma göre değişir. Farklı sınıflar IDisposablefarklı şekillerde uygulanır ve gerekli araştırmaları yapmak size bağlıdır.
Kadarıyla şöyle SqlClientgider, tavsiye edilen uygulama aşağıdakileri yapmaktır:
using (SqlConnection conn = /* Create new instance using your favorite method */)
{
conn.Open();
using (SqlCommand command = /* Create new instance using your favorite method */)
{
// Do work
}
conn.Close(); // Optional
}
Sen olmalıdır çağırıyor Dispose(veya Closebağlantıda *)! Do not çöp toplayıcı bağlantınızı temizlemek için beklemek, bu (en azından) bir sonraki GC döngüsüne kadar havuzda bağlantıları bağlayacağım olacaktır. Eğer ararsanız Dispose, aramak gerekli değildir Closeve usingyapı Disposedoğru şekilde işlenmeyi çok kolaylaştırdığı için , aramak için gerçekten bir neden yoktur Close.
Bağlantılar otomatik olarak toplanır ve bağlantının açılması Dispose/ Closekapatılması bağlantıyı fiziksel olarak kapatmaz (normal koşullar altında). Kendi havuzunuzu uygulamaya çalışmayın. SqlClienthavuzdan alındığında bağlantıda temizleme gerçekleştirir (veritabanı bağlamını ve bağlantı seçeneklerini geri yükleme gibi).
* arıyorsanız, Closebunu istisna açısından güvenli bir şekilde yaptığınızdan emin olun (örn. yakalama veya son olarak engelleme).
conn.Close(); // Optionalİsteğe bağlı değil. Gereksiz ve gereksiz. Nesneyi iki kez imha ediyorsunuz ve bu bazı kod analiz araçları tarafından bir uyarı olarak işaretlenecektir.
using (var x = ..) { x.Dispose(); }, bu durumda xgerçekten "iki kez atılır".
Dispose () öğesini çağırmanız gerekiyor!
Dispose (), geliştiricinin araması içindir, Garbage Collector Finalize () öğesini çağırır. Nesnelerinizde Dispose () öğesini çağırmazsanız, kullandıkları yönetilmeyen herhangi bir kaynak, çöp toplayıcı gelip aramalar bitirilinceye kadar (ve bunun ne zaman olacağını kim bilir) bertaraf edilmeyecektir.
Bu senaryoya Deterministik Olmayan Sonlandırma denir ve .net geliştiricileri için ortak bir tuzaktır. IDisposable uygulayan nesnelerle çalışıyorsanız, üzerlerinde Dispose () öğesini çağırın!
http://www.ondotnet.com/pub/a/oreilly/dotnet/news/programmingCsharp_0801.html?page=last
Bazı nesnelerde Disponse () çağırdığınız ve bağlantısında Close () çağırdığı veya bir dosya tanıtıcısını kapattığı birçok örnek (SqlConnection'da olduğu gibi) olsa da, neredeyse her zaman Dispose () öğesini çağırmak için en iyi bahistir! yakın gelecekte nesneyi yeniden kullanmayı planlamıyorsanız.
Dispose.
Dispose() eğer kullanmadığınız using()bunu uygulayan bir sınıf ile IDisposable. Eğer çağrılan sınıf IDisposable uygular ve kullanımını içindeki sayfaya tamamladıysanız using(), Dispose()(pun amaçlı, bu yüzden beni vur) ile atabilirsiniz . Kullanılması Close()Ancak açıkça kullanan bir şeyle önerilir Open()AFAIK.
Closebağlantı kurduğunuzda, Postgres otomatik olarak bağlantı tanımlayıcısını olarak ayarlar null. O andan itibaren Dispose, önceden ayarlanmış bir sql bağlantı tanımlayıcısı olamaz null.
Çünkü SqlConnectionbağlantının kendisi açısından eşdeğerdirler. Reflector'a göre, Dispose()çağrının Close()yanı sıra , çoğunlukla üyeleri null değerine ayarlayarak birkaç ek bellek boşaltma işlemi yapıyor.
Stream için aslında eşdeğerdir. Stream.Dispose()sadece Kapat () öğesini çağırır.
Component hangi denemek ve çağrı için hiçbir şey görünmüyorClose() . Ben her yerde göremiyorum DBConnectionya SqlConnectionbu bildirimlerin ya içine bağları olduğunu. Ancak DisposeMe()hiçbir yerde referans verilmeyen bir özel var .
Bu hızlı tavsiye uzun bir cevap haline geldi. Afedersiniz.
Tyler'ın güzel cevabında işaret ettiği gibi, arama Dispose()yapmak harika bir programlama uygulamasıdır. Bunun nedeni, bu yöntemin gerekli olan tüm kaynak serbestliğini "bir araya getirmesi" gerektiğidir, böylece gereksiz açık kaynak yoktur. Örneğin, bir dosyaya metin yazdıysanız ve dosyayı kapatamadıysanız (kaynağı serbest bırakın), açık kalacaktır ve GC gelip sahip olmanız gerekeni yapana kadar başka kimse ona yazamaz. yapılır.
Şimdi, bazı durumlarda, üzerinde çalıştığınız sınıfa daha özel "sonlandırma" yöntemleri uygulanacaktır, örneğin StreamWriter.Close(), bu geçersiz kılınır TextWriter.Close(). Aslında, genellikle duruma daha uygundurlar: Close()Örneğin, bir StreamWriter Dispose(), nesneyi girmeden önce akışı ve temel kodlayıcıyı temizler ! Güzel!
Ancak, MSDN'e göz attığınızda Microsoft'un bile bazen çok sayıda kapatıcı ve düzenleyici tarafından karıştırıldığını göreceksiniz. Örneğin, bu web sayfasında bazı örneklerde Close()örtükten önce çağrılır Dispose()( neden örtük olduğunu anlamadıysanız ifadeyi kullanma konusuna bakın ) ve özellikle birinde bunlarla uğraşmazlar. Neden olsun ki? Ben de şaşırdım.
Anladım (ve, vurgulamak gerekirse , bu orijinal araştırma ve kesinlikle yanlış olduğumda itibarını kaybedebilirim), Close()başarısız olabilir, kaynakları açık bırakarak bir istisna vererek Dispose()kesinlikle onları serbest bırakacaktır . Bu yüzden a Dispose()her zaman bir Close()çağrıyı korumalıdır (pun için üzgünüm).
MyResource r = new MyResource();
try {
r.Write(new Whatever());
r.Close()
finally {
r.Dispose();
}
Ve evet, sanırım Microsoft bu örneğe geçti. Belki de zaman damgası dosyaya asla akmaz.
Yarın eski kodumu düzeltiyorum.
Düzenleme: Üzgünüm Brannon, cevabınız hakkında yorum yapamam, ancak Close()bir finallyblokta aramak iyi bir fikir olduğundan emin misiniz ? Sanırım önemli bir temizleme kodu içeren bloğun geri kalanını mahvedebilecek bir istisna.
Brannon's cevap: harika, sadece Close()gerçekten ihtiyaç duyduğunuzda aramayı unutmayın (örneğin akışları ile uğraşırken - .NET SQL bağlantıları hakkında çok fazla şey bilmiyorum).
İDisposable ifadesini yazın ve bu öğeyi çöpe atın. Bu, işlevin ne adlandırıldığına bakılmaksızın, "iDisposable.Dispose" uygulaması olarak yapılandırılan herhangi bir yöntemi çağırır.
IDisposable.Dispose, ancak bu onun adı olduğu anlamına gelmez. Vb.net'te, bir işlevin, işlevin işleviyle ilgili olması gerekmeyen adlara sahip birden çok arabirim üyesine bağlı olabileceğini unutmayın.
using (myObj as IDisposable)
Genellikle Close (), Abort () ve Dispose () 'de sorunla karşı karşıyayız ama size aralarındaki farkı söyleyeyim.
1) ABORT: - Abort çağrıldığında istemci sunucuyu söylemeden bağlantıyı sileceği için sunucuyu bir süre bekleyecek (yaklaşık 1 dakika). Toplu isteğiniz varsa, sınırlı bağlantı havuzunuz için zaman aşımına neden olabileceğinden abort () yöntemini kullanamazsınız.
2) Kapat: - Kapat bağlantıyı kapatmak için çok iyi bir yoldur, çünkü bağlantı kapatıldığında sunucuyu arayacak ve sunucunun bu taraf tarafından da kapanacağını bildirecektir.
Burada, bakmak için bir şey daha var. Bazı durumlarda, hata oluşursa, o zaman İletişim Durumu hatalı olacağından, bu connection.close () kodunu yazmak iyi bir yöntem değildir.
3) Atın: - Bu bir tür kapatmadır ancak bağlantıyı kapattıktan sonra tekrar açamazsınız.
Öyleyse bu şekilde dene,
private void CloseConnection(Client client)
{
if (client != null && client.State == CommunicationState.Opened)
{
client.Close();
}
else
{
client.Abort();
}
}
client != nullTüm kullanımları korumadığı için kontrol yanlış / yanıltıcı. Ayrıca, kod "bu bağlantı açık değil ve kapatılması gerekir" durumuna nasıl alabilirim emin değilim.