30 Aralık 2015 Çarşamba

Dispose ve Finalizer

1. Dispose
Finalizer Garbage Collection'ın bir parçasıdır. Dispose ise GC yani bellek ile ilgili değildir. Bizim kapatmayı istediğimiz managed kaynakları yönetir. Dolayısıyla Dispose kullanmamız memory leak olmadığı anlamına gelmez.

Uygulama Beklenmedik Bir Şekilde Kapanırsa
Eğer using ile kullanıyorsak nesne Dispose edilir. Kullanmıyorsak Dispose edilmez. Örnekte d2 dispose ediliyor ancak d1 dispose edilmez.
IDisposable d1 = new X();

using (IDisposable d2 = new X())
{
    throw new NotImplementedException();
}

d1.Dispose();
Nasıl Kodlarım
IDisposable Örüntüsü yazısına taşıdım.

using ile kullanımı
Normalde Dispose() metodunu elle çağırmamak gerekir. Otomatik olarak çağırmak istersem using örüntüsü ile kullanılır.
using (var another = new Test())
{...}
using ile kullanırken eğer exception atılırsa hatayı bulması zor olabilir.

The C# "using" statement results in a call to Dispose(). This is the same as Close(), which may throw exceptions when a network error occurs. Because the call to Dispose() happens implicitly at the closing brace of the "using" block, this source of exceptions is likely to go unnoticed both by people writing the code and reading the code. This represents a potential source of application errors.

Managed Resource Olarak Stream

Stream sınıflarını using ile kapatmak gerekir. Stream IDisposable arayüzünden kalıtır. FileStream ile kullanılması şöyledir.
using (FileStream f = new FileStream(@"...", FileMode.Create, FileAccess.Write))
{
}
StreamWriter ve StreamReader sınıfları Stream'den kalıtırlar. Dolayısıyla IDisposable arayüzünden kalıtırlar. Bu sınıfların kullanılması şöyledir.
using (StreamWriter sw = new StreamWriter(FileStream))
{
      //Write Logic goes here...
}

using (StreamReader file = new StreamReader(FileStream))
{
     //Read Logc goes here...
}
Managed Resource Olarak Timer
Timer sınıflarının kapatılması iyi olur. Timer, Component vasıtasıyla IDisposable arayüzünden kalıtır.
private void Dispose(bool disposing) {
  if (disposing) {
    timer.Elapsed -= timer_Elapsed;
    timer.Dispose();
  }
}
Dispose Metodunu Elle Çağırırsam Ne Olur ?
Çağrılabilir, hatta birden fazla bile çağrılabilir. Ancak bence yanlış bir kullanım çünkü using varken niçin elle çağıralım?
If an object's Dispose method is called more than once, the object must ignore all calls after the first one. The object must not throw an exception if its Dispose method is called multiple times. Instance methods other than Dispose can throw an ObjectDisposedException when resources are already disposed.

2. Finalizer
Finalizer Nedir?
Finalizer aynı zamanda destructor olarak da isimlendirilir.Eğer sınıf Dispose metodunu gerçekleştiriyorsa, Dispose false ile çağrılır.
~Watchdog() {
    Dispose(false);
}
Sadece loglamak istiyorsak şöyle kodlanır
~destructorCheck() {
   Console.WriteLine("Destructor");
}
Ne Zaman Çalışır ?
GC isteyince veya uygulama kapanırken çalışır. Uygulama kapanırken 2 saniye kadar finalizerlar çalıştırılır. Eğer daha fazla finalizer metodu çalıştırılacak nesne varsa bile süre aşılmaz. Yani finalizer çalışması garanti edilebilen bir metod değildir.



Hiç yorum yok:

Yorum Gönder