2009-07-02 12 views

cevap

22

Evet. Etkinlik yayıncıları, nesnelere referanslar tutuyor ve topladıkları çöplerin toplanmasını engelliyorlardı.

Ne olduğunu görmek için bir örneğe bakalım. İki dersimiz var; bir başka bunu tüketir, bir olay ortaya: ClassB Sınıf A örneği başvurusu saklamaz nasıl

class ClassA 
{ 
    public event EventHandler Test; 
    ~ClassA() 
    { 
     Console.WriteLine("A being collected"); 
    } 
} 
class ClassB 
{ 
    public ClassB(ClassA instance) 
    { 
     instance.Test += new EventHandler(instance_Test); 
    } 

    ~ClassB() 
    { 
     Console.WriteLine("B being collected"); 
    } 

    void instance_Test(object sender, EventArgs e) 
    { 
     // this space is intentionally left blank 
    } 
} 

Not; Sadece bir olay işleyicisini alır.

Şimdi, nesnelerin nasıl toplandığını görelim. Senaryo 1:

ClassB temp = new ClassB(new ClassA()); 
Console.WriteLine("Collect 1"); 
GC.Collect(); 
Console.ReadKey(); 
temp = null; 
Console.WriteLine("Collect 2"); 
GC.Collect(); 
Console.ReadKey(); 

Bir ClassB örneği oluşturuyoruz ve geçici değişkeni kullanarak ona bir başvuru tutuyoruz. ClassA'nın yeni bir örneğini geçiririz, burada herhangi bir yere herhangi bir referans kaydetmiyoruz, bu yüzden ClassB kurucusunun tamamlanmasından hemen sonra kapsam dışı kalıyor. ClassA kapsam dışı kaldığında ve ClassB kapsam dışı kaldığında bir kez çöp toplayıcısını çalıştırıyoruz. çıkışı:

Collect 1 
A being collected 
Collect 2 
B being collected 

Senaryo 2:

ClassA temp = new ClassA(); 
ClassB temp2 = new ClassB(temp); 
temp2 = null; 
Console.WriteLine("Collect 1"); 
GC.Collect(); 
Console.ReadKey(); 
temp = null; 
Console.WriteLine("Collect 2"); 
GC.Collect(); 
Console.ReadKey(); 

ClassA yeni bir örneği oluşturulur ve buna bir referans sıcaklığı değişken olarak depolanır. Daha sonra, ClassA örneğini geçici olarak iletilen yeni bir ClassB örneği oluşturulur ve temp2'ye bir başvuru kaydederiz. Daha sonra temp2'yi null olarak ayarladık ve ClassB örneğinin kapsam dışı kalmasını sağladık. Daha önce olduğu gibi, her örnek kapsam dışına çıktığında çöp toplayıcısını çalıştırdık. Sonuç olarak, sonuçlandırmak için:

. Bir olayı ortaya çıkaran durumun kapsamı dışında kalması durumunda, olay işleyicilerinin bağlanmış olup olmadığına bakılmaksızın, çöp toplama için kullanılabilir. Bir olay işleyicisinin başka bir durumda bir olaya bağlandığı bir örnek varsa, olay işleyicisi ayrılıncaya kadar çöp toplama için kullanılamaz veya olay işleyicisinin eklendiği örnek çöp toplama için kullanılabilir duruma gelir.

9

Yalnızca olaylar kullanan nesne uzun ömürlü olması durumunda olayları unhook gerekir, ancak nesne olay başka türlü kısa ömürlü olacağını çengel (ve çöp oldukça hızlı bir şekilde toplanmış olsun).

Bu durumda, takma işlemi başarısız olursa bellek sızıntısına ne kadar neden olur, çünkü kısa ömürlü nesneniz GCed olamaz - çünkü uzun ömürlü nesnedeki olay bir temsilci tarafından tutulur; kısa ömürlü nesneye bir referans tutar. Kısa ömürlü nesneye hala bu temsilci tarafından başvurulduğundan, çöp toplanamaz.

Statik olaylar, tanım gereği uzun ömürlüdür - program çıkana kadar çalışırlar. Statik bir etkinlik çektiyseniz, işiniz bittiğinde kesinlikle çıkarmalısınız.

İki nesne de yetim olmak üzereyse, takılı değil.

5

Bir etkinliğe abone olmak, aboneye güçlü bir başvuruyla sonuçlanır. Bunun nedeni, kapakların altında olayların temsilciler olması ve örnek yöntemlere temsilciler, nesne başvurusu ve gerçek yöntemin birleşimidir. Abonelikten çıkmazsanız, yayıncı referansları korumaya devam edecek ve abone nesneleri yayıncı canlı olduğu sürece gerçekten yetim edilmeyecektir (ve GC'ed).

Tersi doğru değil, abone olunan nesnenin yayıncıya herhangi bir referansı yok.

İlgili konular