Using Kullanımı ve Otomatik Dispose()

Merhaba;
Bu makalemizde Using ifadesi kullanımı, nasıl çalıştığını ve bellek yönetimine katkısını incelemeye çalışacagız.

Yazılımda performans ve bellek yönetiminin önemini biliyoruz. Küçük çaplı projelerde .Net CLR (Common Language RunTime) sayesinde kodları çalıştırmak
ve bellek yönetimini otomatik olarak yapma görevini üstlensede büyük çaplı, verilerin yoğun aktığı bir projede bellek yönetimini mümkün olduğu kadar elimizde tutmamız gerekir. CLR de bu görevi GC (Garbage Collector) mekanızması sayesinde yerine getirmektedir.

Bilindiği gibi kod tarafında oluşturulan referans tipler için bellekte heap bölgesinde alan tahsis edilir ve işi bittikden sonra bellekten atılırlar ama bellekten atılma süreleri belirsizdir.

Belirsiz dedik çünkü GC nin ne zaman çalışacağı belli değildir. (Kendi içinde mutlaka bir mekanizmaya bağlıdır.)

Direk şu fikir akla gelebilir ozaman bizde GC yi görev başına çagırırız! Evet bu da bir yöntem ama sadece gerçekten gerektiğinde kullanılması gerekir. Çünkü sık sık GC kullanmak performans kaybına neden olur.

Ayrıca oluşturulan nesnelere null değeri atamak o nesneyi bellekten atmaz sadece üzeri kapatılarak erişilmez hale getirir ama arka tarafta bellek alanında var olmaya devam eder.

Ozaman ne yapılmalı ?
IDispose arayüzünden implemente edilmiş Dispose() metodu kullanmalı.

Kullandığımız bir çok nesne Dispose() metoduna sahiptir ve tamamıda IDispose interface inde kalıtım yoluyla geçmiştir.

İsterseniz şimdi kısa bi örnek ile ilerleyelim.

SqlConnection sqlCon = null;
SqlDataAdapter adp = null;
try
{
sqlCon = new SqlConnection("Server=.;Database=AdventureWorks;Uid=sa;Pwd=1234");
adp = new SqlDataAdapter("Select * From Production.Product", sqlCon);
adp.Fill(dt);
}
catch (Exception ex)
{
throw new Exception ("hata", ex);
}
finally
{
sqlCon.Close();
adp.Dispose();
sqlCon.Dispose();
}

Görüldüğü gibi finally blogu her durumda çalışağı için SqlDataAdapter ve SqlConnection nesneleri Dispose işlemine tabi tutulmuşlardır.

Buraya kadar anladık ama using bunun neresinde diyebilirsiniz. Şimdi sıra bunun cevabını vermeye geldi.

using anahtarı uyğuladıgınız sınıflarda otomatik olarak dispose çalıştırır.
Yani bunun anlamı finaly blogunda ayrıca adp.Dispose(); şeklinde metoduğu çagırmanıza gerek kalmaz using bizim için bunu yapar demektir.

usin ifadesi nesnenin yaşam sürecini belirtir.

using(SqlCommand cmd=new SqlCommand("Select * From Production.Product", sqlCon))
{
// işlenen komutlar
// SqlCommand yaşam alanı
}

Örnekte bakacak olursak SqlCommand yaşam alanı { } arasında son bulacaktır. Otomatik olarak Dipose() uygulanmış olur.

Çok kullanıcılı bir programda bunun ne kadar önemli oldugunu tahmin edersiniz.

Sizlerde geliştirdiğiniz sınıflara aşagıda ki örnegi uygulayarak usin ifadesiyle otomatik dispose a tabi tutabilirsiniz.

class MyClass:IDisposable
{

public void Dispose()
{
//Dispose kodlarınız...
GC.SuppressFinalize(this);
}
}


Umarım faydalı olmuştur...

9 yorum

teşekkürler faydalı makele

Cevapla

hep merak ettiğim bir konuydu çok açıklayıcı olmuş teşekkürler

Cevapla

1 bir sorum olucaktı siz nesneleri kullanırken using yaparsanız otomatik dispose devreye girer demişsiniz, ancak bir yerde görmüştüm using kullanıldığı halde

try catch bloğunda son finaly kısmında

kullanılıyordu, o zaman finaly kısmı gereksiz bir alan kodu yazan kişi yanlış yazmış ?

using (TransactionScope transaction = new TransactionScope())
{
try
{
_NereyeIstersenEntities.SaveChanges();
transaction.Complete();
return true;
}
catch (Exception)
{
return false;
}
finally
{
transaction.Dispose();
}
}


2 bazı class ların Dispose yada Idispose dan implemente edildiğini görüyorum bu ne işe yarıyor ? eğer bu şekilde kullanırsam o zaman bu class ı x bir yerde kullanırken using yada dispose dememe gerek yokmu ? yoksa using yada dispose ile farkı nedir ? yada yokmudur :)
public class typeItems :IDisposable
{

}

3. SuppressFinalize çoğu yerde nesnenin bellekten atılmamasını engellediği yazılmış ama bazı yerlerde tam tersi nesnenin atılması içindir denmiş,SuppressFinalize ne işe yarıyor ? dispose ile görevi aynımı ?

http://msdn.microsoft.com/en-us/library/vstudio/b1yfkh5e(v=vs.100).aspx

burdada yine constructor da
Dispose(true);
GC.SuppressFinalize(this);

beraber kullanılmış, GC.Collection(); yada SuppressFinalize kullanmış

ve son olarak constructor için ~Base() kullanışmış bu tilda ne işe yarıyor
çok teşekkürler

Cevapla

1. Bu kullanımı için özel bir sebebi varmı bilemeyiz. Ama görünene göre bir daha Dispose metodunu çağırmasına gerek yok. Yada böyle kullanacaksa using kullanımına gerek yok.
Dediğim gibi özel bir sebebi yada tercihi olabilir.
try- catch blokları performanası olumsuz etkiler bu yüzden gereken yerlerde kullanılmalı.

2. madde IDisposable interfaceyi implemente etmek bu makelenin konusunu oluşturuyor, yani objeleri bellekten kendi kontrolümüzde atabilmek için IDisposable interface ni implemente ediyoruz. Her class için IDisposable kullanmanıza gerek yok. Maliyetli objeler için kullanılır. Verdiğiniz örnekte ki gibi entity objeleri bağlantı objeleri vs. gibi.

3. Bellekten atılması içindir.
~Base() Deconstructor dediğimiz yıkıcı metod dur. Konuyu ayrıca araştırmanızda fayda var.
Umarım yeterince açıklayıcı olmuştur.

Cevapla

güzel yazı olmuş ellerine sağlık.
Bir sorum olacak mesela bir nesneye sürekli ihtiyacımız onu sürekli new ile oluşturup sonra dispose etmek mi yoksa globale almak mı ?
Aslında cevabı biliyorum globale almak mantıklı olur ama senin ve arkadaşların görüşünü almak isterim

Cevapla

Bu kullanılan yere göre değişir tabi ki ama genelde maliyetli objeler için dispose kullanıyoruz.
Hep aynı objeye ihtiyacınız varsa ben C şıkkı diyorum :) Singleton Pattern (Tasarım Deseni) kullanılmalı.

Cevapla

Harika bir makale olmuş emeğiniz için teşekkür ederim.
Yazılarınızın devamını dilerim.

Cevapla

tertemiz açıklamalar ver elinize sağlık

Cevapla

Yorum Gönder