Rüzgara karşı tükürmeyin!

Ana sayfa » .Net Bellek Yönetimi 2: Bileşenler, Diziler ve COM

Kategoriler: .Net/C#

Anlamsız veriler nesnelerin geri dönüşümü gerektiğinde değil ihtiyaç oldukça toplanmaktadır. Eğer bir bileşen, örneğin açık bir kaynağı elinde tutuyorsa ve bu kaynağın bir başka program tarafından kullanılması için serbest bırakılması gerekiyorsa bunu çöp toplama sisteminin insafına bırakmamalıyız.

Bileşene yönelik tüm referansları kaldırmamız sorunu çözmez. Çünkü bileşen, ihtiyaç duyduğu kaynağa yaptığı referansı bir sonraki çöp toplama işlemine kadar elinde tutmaya devam edecektir. Sınıflarımızı Dispose() metodu ile yönetiyorduk bileşenlerimizi Dispose(bool ) u kullanarak yönetebiliriz. Dispose(bool) kullandığımızda, Dispose() kullanmamıza gerek yoktur, Dispose() a yapılan çağrı Dispose(bool) u çağırır.

Dispose(bool) kullanırken bazı kurallara uymamız gerekir.

1. Dispose(bool) değeri true olan bir argümanla çağrıldığında, sizin versiyonunuz, bileşenle ilgili yönetilen ve yönetilmeyen tüm kaynakları serbest bırakmalıdır. Eğer false bir argümanla çağrıldıysa, sizin versiyonunuz eğer var ise sadece yönetilmeyen kaynakları serbest bırakmalıdır.
2. Dispose(bool), herhangi bir sakınca doğmadan tekrar tekrar çağrılabilmelidir.
3. Dispose(bool), temel sınıf uygulamasını çağırmalıdır.
4. Bileşenimizin yok edicisi sadece Dispose(false) u çağırmalıdır.

Şekil 1 :

using System;

using System.ComponentModel;

namespace Cevik.Application.Common

{

    public partial class Bilesen1 : Component
    {
        bool isDisposed; //bileşen dispose edildiyse true'dur.

        public Bilesen1()
        {
            InitializeComponent();
            isDisposed = false;
            //...
        }

        public Bilesen1(IContainer container)
        {
            container.Add(this);
            InitializeComponent();
            isDisposed = false;
        }

        ~Bilesen1()
        {
            Dispose(false);
        }

        protected override void Dispose(bool disposing)
        {
            if (!isDisposed)
            {
                if (disposing)
                {
                    // kaynakları serbest bırak
                    //...
                    isDisposed = true;
                }
                base.Dispose(disposing);
            }

        }
    }
}

Daha iyi bir yazım adına ve gerçek dünyada bileşenimizin hata ile karşılaşmaması için temel metotlarımızın (genelde genel(public)) nesne dispose edilmiş ise işlemi gerçekleştirmemesi veya hata fırlatması gerekir. Kuşkusuz hata fırlatmayı tercih etmemiz iyisidir.

using System;
using System.ComponentModel;
using System.IO;

namespace Cevik.Application.Common
{

    public partial class Bilesen1 : Component
    {
        bool isDisposed; //bileşen dispose edildiyse true’dur.
        int difference = 0;

        public Bilesen1()
        {
            InitializeComponent();
            isDisposed = false;
            difference = 2;
            //…
        }

        public Bilesen1(IContainer container)
        {
            container.Add(this);
            InitializeComponent();
            isDisposed = false;
            difference = 2;
        }

        ~Bilesen1()
        {
            Dispose(false);
        }

        public int GetResult(decimal a, decimal b)
        {
            if (isDisposed)
                throw new Exception(”Bileşen Dispose edilmiş”);
            return a * b / 2;
        }

        protected override void Dispose(bool disposing)
        {
            if (!isDisposed)
            {
                if (disposing)
                {
                    // kaynakları serbest bırak
                    //…
                    isDisposed = true;
                }
                base.Dispose(disposing);
            }
        }
    }
}

Açıkça dispose() metodunu çağırmak yerine .Net Bellek Yönetimi makaleme katkı yapan Tolga Güler’in dediği gibi IDisposable arayüzünden türeyen her nesne için using ifadesi kullanılabilir. Kullanılmalıdır, çünkü kodun okunmasını ve yazımını kesinlikle kolaylaştıracaktır. Using ifadesinin kullanımı:

//bloğun sonunda dispose() çalıştırılacaktır.
using (Bilesen1 bil1 = new Bilesen1())
{
    //bil1'i kullanır
}

Yığınlar için stackalloc ifadesini kullanarak yığından bellek alanı alabiliriz. Yalnızca değişkenlere ilk değer atanırken kullanılabilir.

int * a = stackalloc int[10];

Bu kullanımın avantajı, çöp toplama işlemine tabi tutulmazlar, bunun yerine blok çalıştığı sürece varlıklarını sürdürürler.

Elimizdeki bir COM nesnesi ise System.Runtime.InteropServices.Marshal.ReleaseComObject(object) işlevi aracılığı ile yok etme işlevini yapabiliriz.

« Asp.Net’de Ashx Sayfaları
.Net Remoting’e Bir Bakış »

Alakalı (olabilecek) yazılar

Alakasız (yüksek ihtimal) yazılar




Sen de yorum yazabilirsin!