Olay işleyicileri çöp toplama işlemini engelliyor mu?


183

Aşağıdaki kod varsa:

MyClass pClass = new MyClass();
pClass.MyEvent += MyFunction;
pClass = null;

PClass çöp toplanacak mı? Yoksa olayları meydana geldiklerinde tetiklemeye devam edecek mi? Çöp toplamaya izin vermek için aşağıdakileri yapmam gerekecek mi?

MyClass pClass = new MyClass();
pClass.MyEvent += MyFunction;
pClass.MyEvent -= MyFunction;
pClass = null;

11
Geçici olarak bu soruyla ilgilenen okuyuculara, çöp toplama işleminin gerçekleşmesini engellemeyen hafif olaylara / zayıf olay kalıplarına aşina olmanın faydalı olabileceğini önereceğim. Bu konuda iyi bir SO önyükleme stackoverflow.com/questions/185931/…
fostandy

20
Posterity için not: referansı null değerine ayarlamak, referansın kapsamını bir satır genişleterek çöp toplayıcıyı geciktirir. .NET VB6 değildir.
John Saunders

Yanıtlar:


207

"PClass çöp toplanacak mı?" Sorusu için: olay aboneliğinin (yayıncı olarak) pClass toplanması üzerinde hiçbir etkisi yoktur.

Genel olarak GC için (özellikle hedef): MyFunction'ın statik mi yoksa örnek tabanlı mı olduğuna bağlıdır.

Bir örnek yöntemine temsilci (olay aboneliği gibi), örneğe bir başvuru içerir. Evet, bir etkinlik aboneliği GC'yi engelleyecektir. Ancak, olayı yayınlayan nesne (yukarıdaki pClass) toplama için uygun olur olmaz, bu bir sorun olmaktan çıkıyor.

Bunun tek yönlü olduğunu unutmayın; örneğin:

publisher.SomeEvent += target.SomeHandler;

"yayıncı", "hedef" i canlı tutar, ancak "hedef", "yayıncı" yı canlı tutmaz.

Yani hayır: pClass yine de toplanacaksa, dinleyicilerin aboneliğini iptal etmeye gerek yoktur. PClass (uzun MyFunction ile bir örneği değil) uzun ömürlü olsaydı o kadar ancak sonra pClass, hayatta bu örneği tutmak olacağını hedef toplanacak istiyorsanız çıkmak için gerekli.

Bununla birlikte, statik olaylar, bu nedenle, örnek tabanlı işleyicilerle kullanıldığında çok tehlikelidir.


6
Eğer soru "pClass çöp toplanacak mı" ise, o zaman cevap "bu doğru olup olmamasına bağlıdır ..." aslında doğru değil. Marc'ın kendisinin daha da aşağıya not ettiği gibi, hiçbir şeye bağlı değildir.
Tor Haugen

@Tor - Fuar yeterince - ı açıklamak edeceğiz
Marc Gravell

Bir olay aboneliği temsilcisi yalnızca bir yolu işaret etse de, bununla birlikte bir olaydan aboneliği iptal etme niyeti olan bir abonenin yayıncıya bir tür referans vermesi gerekir. Bir olabilir WeakReferenceve bazı durumlarda bu iyi bir fikir olabilir, ancak çoğu zaman güçlü bir fikir olacaktır.
supercat

Harika bir cevap, çünkü aynı zamanda sorunun diğer yarısına da hitap ediyor (sorulmadı): yayıncı , abonenin GC'lı olmasını engelleyecektir .
Bob Sammers

Evet ve @BobSammers'ın dediği gibi, Form / Pencere gibi kısa ömürlü bir örneğin veri sağlayan bir Singleton gibi uzun ömürlü bir hizmete abone olması gerçekten bir sorun olabilir: ve yüksüz olduklarını düşünsek bile nesneler hafızada tutulur! Bu nedenle, Etkinlikleri kullanırken çok dikkatli olun. Büyük yazılımımız için olayları kötüye kullandık ve daha sonra çözmek çok zor.
Elo

9

Evet, pClass çöp toplanacak. Olay aboneliği, pClass için herhangi bir referans olduğu anlamına gelmez.

Bu nedenle, pClass'ın çöp toplanması için işleyiciyi ayırmanız gerekmeyecektir.


8

Bir bellek parçasına artık atıfta bulunulmadığı anda çöp toplama adayı olur. Sınıfınızın örneği kapsam dışına çıktığında, artık programınız tarafından başvuruda bulunulmaz. Artık kullanılmamaktadır ve bu nedenle güvenle toplanabilir.

Bir şeyin toplanıp toplanmayacağından emin değilseniz, kendinize şu soruyu sorun: hala bir referans var mı? Olay işleyicilerine, başka bir yolla değil, nesne örneği tarafından başvurulur.


0

pClassçöp toplanacak. Yukarıdaki kod pasajı başka bir sınıfın içinde olup olmadığını ayarladığınız yoksa Ancak, bu sınıfın örneği temizlenecek olmayabilir pClassiçin null.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.