Berk Akademi
Birebir ders başvurusu Ücretsiz ön görüşme Ana Sayfa

C# "ObjectDisposedException" Hatası Neden Alınır?

csharp-objectdisposedexception-hatasi-neden-alinir
Bu yazıda neler var?
  1. ObjectDisposedException hatası neden alınır?
  2. IDisposable, Dispose ve using bloğu nasıl çalışır?
  3. using kapsamı dışında erişim: çalışan MemoryStream örneği
  4. ObjectDisposedException kaynağını üç teşhis yoluyla bul
  5. ObjectDisposedException nasıl düzeltilir?
  6. Sık Sorulan Sorular

C# ObjectDisposedException hatası, IDisposable kullanan bir nesne Dispose edildikten sonra onun metotlarına veya özelliklerine yeniden erişilmeye çalışıldığında alınır. Nesnenin referansı hâlâ bir değişkende, alanda ya da parametrede bulunabilir; ancak bu durum nesnenin kullanılabilir kaynaklarının hâlâ açık olduğu anlamına gelmez.

Dispose sonrasında oluşan davranış her tür için aynı değildir. Bazı üyeler çağrıldığında ObjectDisposedException oluşabilirken, bazı üyeler türün sözleşmesine göre farklı davranabilir. Sorunu bulmak için nesnenin nerede oluşturulduğu, nerede Dispose edildiği ve hangi noktada yeniden kullanılmaya çalışıldığı izlenmelidir.

ObjectDisposedException hatası neden alınır?

Bir nesne oluşturulduğunda yalnızca bellekte bir referans elde edilmez; nesne bazen işletim sistemi kaynağı, akış, dosya, bağlantı veya başka bir yönetilmesi gereken kaynakla ilişkilendirilir. Dispose çağrısı, bu kaynağın artık kullanılmayacağını nesneye bildirir ve türün tasarımına göre gerekli temizleme işlemlerini başlatır. Temizleme tamamlandıktan sonra aynı nesneyi kullanmaya devam etmek geçersiz bir yaşam döngüsü oluşturabilir.

Bu hatanın yaygın nedenlerinden biri, nesnenin yaşam süresini yöneten kod ile nesneyi kullanan kodun birbirinden ayrılmasıdır. Örneğin bir metot oluşturduğu akışı kapattıktan sonra aynı akışı çağıran metoda döndürebilir. Dışarıdaki kod geçerli bir referans almış olsa bile, referansın gösterdiği nesne artık kullanılabilir durumda olmayabilir.

Bir başka neden, using kapsamından çıkan bir nesnenin kapsam dışındaki başka bir değişken veya alan üzerinden kullanılmaya devam etmesidir. Burada sorun referansın silinmesi değildir. Sorun, referansın hâlâ aynı nesneyi göstermesine rağmen o nesnenin kaynak yaşam süresinin sona ermiş olmasıdır.

C# bilginin hangi konularda güçlendirilmesi gerektiğini görmek için C# bilgi testini kullanabilirsin. Bu araç bir C# programı değil, mevcut bilgi düzeyini ölçmeye yardımcı olan bir değerlendirmedir.

IDisposable, Dispose ve using bloğu nasıl çalışır?

IDisposable, Dispose ve using bloğu nasıl çalışır?

IDisposable, kaynak kullanan nesnelerin yaşam döngüsünü açıkça yönetmek için kullanılan bir sözleşmedir. Bu arayüzü uygulayan türler, genellikle kaynak bırakma işlemlerini Dispose metodu üzerinden sunar. Dispose çağrıldığında nesnenin belleği hemen yok olmak zorunda değildir; belleğin geri alınması çöp toplayıcının görevidir. Ancak dosya, akış veya bağlantı gibi kaynakların kullanımını sonlandırma sorumluluğu Dispose işlemine aittir.

using bloğu, nesnenin yalnızca belirli bir kapsam içinde kullanılacağını ifade eder. Kapsam sona erdiğinde, normal akış gerçekleşse de blok içinde başka bir hata oluşsa da Dispose çağrısının yapılmasını otomatikleştirir. Bu nedenle using, temizleme kodunun unutulması ihtimalini azaltır ve nesnenin yaşam süresini daha görünür hâle getirir.

“Dispose edilen nesneyi yeniden kullanmak yerine, nesnenin sahibi ve yaşam süresi belirlenmelidir.”

Buradaki sahiplik, nesneyi kimin oluşturduğundan çok, kullanım süresini ve Dispose sorumluluğunu kimin yönettiğiyle ilgilidir. Nesneyi oluşturan kapsam onu yalnızca kendi işlemi boyunca kullanacaksa Dispose işlemi de aynı kapsamda yapılmalıdır. Başka bir metoda gönderilecek nesnenin yaşam süresi ise çağıran ve çağrılan kod arasında açıkça belirlenmelidir.

Kaynak yaşam döngüsü, yalnızca tek bir dile ait ayrıntı değildir. Yazılım öğrenme sürecini farklı hedeflerle birlikte planlamak için genel yazılım eğitimi sayfasındaki program başlıklarını inceleyebilirsin.

using kapsamı dışında erişim: çalışan MemoryStream örneği

using kapsamı dışında erişim: çalışan MemoryStream örneği

using bloğu, bloğun sonunda içindeki nesne için Dispose çağrılmasını sağlar. Değişkenin referansı blok dışına taşınsa bile nesnenin kaynak kullanım süresi sona erer. Aşağıdaki örnekte aynı MemoryStream değişkeni üzerinden Length özelliğine erişilmeye çalışılır:

using System;
using System.IO;

class Program
{
    static void Main()
    {
        MemoryStream stream = new MemoryStream();

        using (stream)
        {
            stream.WriteByte(42);
        }

        try
        {
            Console.WriteLine(stream.Length);
        }
        catch (ObjectDisposedException ex)
        {
            Console.WriteLine(ex.GetType().Name);
        }
    }
}

Beklenen çıktı tek satırdır:

ObjectDisposedException

using bloğu kapandığında stream.Dispose() çağrılır. stream değişkeni hâlâ aynı nesnenin referansını tutar, ancak MemoryStream için kullanım yaşam süresi tamamlanmıştır. Bu nedenle hata yalnızca yeni veri yazma gibi işlemlerde değil, bu örnekte olduğu gibi stream.Length özelliğini okumaya çalışırken de ortaya çıkabilir.

ObjectDisposedException kaynağını üç teşhis yoluyla bul

Hatanın kaynağını bulmak için yalnızca istisnanın oluştuğu satıra bakmak yeterli olmayabilir. Nesnenin nerede oluşturulduğunu, kimin sahibi olduğunu ve hangi noktada elden çıkarıldığını birlikte incelemek gerekir.

using bloğunun dışına taşan nesne

using içinde oluşturulan veya kullanılan bir nesne alan değerine atanabilir, dönüş değeri olarak gönderilebilir, bir callback içine aktarılabilir ya da başka bir metoda parametre olarak verilebilir. Referansın dışarı taşınması, nesnenin yaşam süresini uzatmaz. Dışarıdaki kod, using sona erdikten sonra bu nesneyi kullanıyorsa hata oluşabilir.

erken Dispose çağrısı

Bazen nesneyi kullanan kod tamamlanmadan başka bir metot, bileşen veya sahip nesne Dispose çağırır. Özellikle aynı akışın birden fazla metot arasında paylaşıldığı durumlarda, elden çıkarma işleminin hangi kod tarafından ve hangi sırada yapıldığını kontrol et. Kullanım devam ederken yapılan erken Dispose çağrısı, sonraki erişimi geçersiz hâle getirebilir.

yaşam süresi yanlış tasarlanmış alan

Bir sınıf alanının tuttuğu kaynak, alanı kullanan nesneden daha kısa ömürlü olabilir. Örneğin uzun süre yaşayan bir nesne, yalnızca geçici bir using bloğu için oluşturulmuş akış nesnesini alanında saklarsa ilerleyen bir metot geçersiz bir referansı kullanabilir. Burada alanın sahibi ile kaynağın gerçek sahibi ve kullanım süresi birbirine uymuyor olabilir.

Teşhis için şu kontrol sırasını izle:

  1. Nesnenin oluşturulduğu yeri bul.
  2. Nesnenin sahibi olan kodu belirle.
  3. Tüm Dispose ve using noktalarını izle.
  4. Alan, parametre ve dönüş değeri akışını kontrol et.
  5. İstisna yığın izinde ilk geçersiz erişim noktasını incele.
“Dispose edilen nesneyi yeniden kullanmak yerine, nesnenin sahibi ve yaşam süresi belirlenmelidir.”

Bu adımlardaki C# kavramlarını ne ölçüde bildiğini görmek için ücretsiz C# bilgi testini yalnızca seviye ölçümü amacıyla kullanabilirsin.

ObjectDisposedException nasıl düzeltilir?

ObjectDisposedException hatasını düzeltmek için Dispose edilmiş nesneye erişimi engellemen gerekir. Bunun yolu, kullanımı nesnenin geçerli olduğu kapsama taşımak veya sahiplik ile yaşam süresini yeniden tasarlamaktır.

Kullanımı nesnenin geçerli olduğu kapsama taşı

Kaynak yalnızca bir metotta gerekiyorsa onu using içinde oluştur, kullan ve kapat. Metodun dışına nesnenin kendisini değil, üretilen metni, byte[] verisini veya sonucu döndür. Böylece çağıran kod, artık geçerli olmayan kaynağa değil, kaynaktan elde edilen veriye erişir.

Sahipliği ve yaşam süresini yeniden tasarla

Nesneyi kim oluşturuyorsa sahipliği ve kullanım süresini kim yönetiyorsa bu sorumluluklar açık olmalıdır. Yalnızca iç kullanım için oluşturulan kaynakları ilgili metotta kapat. Çağıran kodun sahip olduğu bir kaynağı, kullanım bitmeden Dispose etme. Uzun ömürlü alanların Dispose zamanını da onları kullanan bileşenin yaşamıyla hizala.

  • Kaynağı hangi kod oluşturuyor?
  • Dispose çağrısı hangi kodun sorumluluğunda?
  • Nesne, kapatıldıktan sonra başka bir metot, alan, görev veya geri çağırım tarafından kullanılıyor mu?
Teşhis Sahiplik veya yaşam süresi işareti Öncelikli çözüm
Kapsam using bittikten sonra aynı kaynak kullanılıyor Kullanımı kapsama taşı, sonucu döndür
Sahiplik Bir metot, çağıranın verdiği kaynağı kapatıyor Sahipliği netleştir, çağıranın kaynağını kapatma
Yaşam süresi Alan, görev veya geri çağırım kapanmış nesneyi paylaşıyor Ömrü bileşenle hizala, gerekirse yeniden oluştur

Kaynak kısa ömürlü ve durumu yeniden kurulabilir olduğunda yeni bir örnek oluşturmak düşünülebilir. Ancak oturum, işlem veya korunması gereken bir durum söz konusuysa yalnızca nesneyi yeniden oluşturmak yeterli olmayabilir. Bu durumda sahibi ve yaşam süresi yeniden tasarlanmalıdır.

“Dispose edilen nesneyi yeniden kullanmak yerine, nesnenin sahibi ve yaşam süresi belirlenmelidir.”

Yazılım öğrenme seçenekleri hakkında genel bilgi edinmek için genel yazılım eğitimi sayfasını inceleyebilirsin.

Sık Sorulan Sorular

Dispose çağrısından sonra nesne yeniden oluşturulmalı mı?

Her zaman değil. Kaynak kısa ömürlü ve durumu kolayca yeniden kurulabilir ise yeni örnek oluşturulabilir. Oturum veya işlem durumu korunacaksa sahiplik ve yaşam süresi yeniden ele alınmalıdır.

using bloğu bittikten sonra değişken neden hâlâ nesneye erişebiliyor?

using bloğu sona erdiğinde Dispose çağrılır, fakat değişkenin referansı otomatik olarak null yapılmaz. Değişken nesneyi göstermeye devam eder, ancak sonraki kullanım nesnenin türüne bağlı olarak ObjectDisposedException oluşturabilir.

ObjectDisposedException ile NullReferenceException arasındaki fark nedir?

ObjectDisposedException, var olan fakat yaşam süresi sona ermiş bir nesnenin kullanılmaya çalışıldığını gösterir. NullReferenceException ise değişkenin herhangi bir nesneyi göstermediği durumda üyeye erişildiğini belirtir.

Bir metot aldığı IDisposable nesneyi kendisi Dispose etmeli mi?

Genellikle hayır. Nesneyi çağıran kod oluşturup sahipleniyorsa metot onu kullanım bitmeden kapatmamalıdır. Nesne metot içinde oluşturulmuş ve yalnızca o metotta kullanılıyorsa Dispose sorumluluğu o metoda ait olabilir.

Bu hatayı çözmenin anahtarı, nesnenin yalnızca nasıl kapatıldığını değil, kimin tarafından oluşturulup ne zamana kadar kullanılacağını da netleştirmektir.

Bu içerik aradığın cevabı verdi mi?
Yanıtın, hangi yazıları geliştirmemiz gerektiğini anlamamıza yardımcı olur.
Bu içeriğin üretilmesinde yapay zeka araçlarından destek alınmıştır.

Bu konudan sonra ne okuyabilirsin?

Tüm yazılar

İlgili Eğitimler

Berk Keskin, yazılım geliştirici ve eğitmen
Yazar

Berk Keskin Kimdir?

Yazılıma 12 yaşında başladı; İzmir Ekonomi Üniversitesi'ni bölüm birincisi ve yüksek şeref öğrencisi olarak tamamladı. Bugün yalnızca eğitim vermekle kalmıyor, sektörde aktif olarak yazılım projeleri geliştiriyor ve gerçek dünya deneyimini birebir derslerine taşıyor. Ezberden uzak, mühendislik zihniyetini merkeze alan sürdürülebilir öğrenme sistemleri tasarlayarak sorgulayan, üreten ve problem çözebilen yeni nesil yazılımcılar yetiştiriyor.

Sektörel Deneyim & Projeler

  • Ticarify Entegrasyon Yazılım logosu CEO Ticarify Entegrasyon YazılımPazaryerleri ve e-ticaret sitelerine otomatik e-fatura kesimi, sipariş ve kargo takibi hizmetleri sunan e-Dönüşüm platformunun API mimarisini ve yazılım ekibini yönetmektedir.
  • Benim Düğünüm logosu CEO Benim DüğünümDijital etkinlik ve anı paylaşım platformu.
  • Siberdizayn logosu Yazılım Ekibi Lideri SiberdizaynYüksek anlık oyuncu trafiğine sahip oyun kontrol panelleri ve sunucu altyapıları geliştiren yazılım ekibine liderlik etmektedir.
  • MEDYOGRAFYA 360° Dijital Çözümler logosu Dijital Strateji Lideri MEDYOGRAFYA 360° Dijital ÇözümlerŞirketlerin dijital çözümlerde uzun vadede nasıl ilerlemesi gerektiği ve dijital dönüşüm süreçlerinin yönetilmesine destek olmaktadır.
  • İzmir Ekonomi Üniversitesi logosu Danışma Kurulu Üyesi İzmir Ekonomi ÜniversitesiMezun olduğu üniversitesinde, Bilgisayar Programcılığı bölümünün akademik müfredatını güncel sektör ihtiyaçlarına göre şekillendirmek adına Danışma Kurulu'nda görev almaktadır.
WhatsApp Hemen Ara