için başvuruda bulunur Bellek sızıntılarını önlemek için WeakEventManager kullanıyorum ve bunları aşırı kullanmaya başladım. Bu işe yaramazsa o, Şimdi ben çabuk farkWeakEventManager, Abone
public static void AddWeakPropertyChanged(this INotifyPropertyChanged item, Action handler)
{
PropertyChangedEventManager.AddHandler(item, (s, e) => handler(e.PropertyName), string.Empty);
}
: ben gibi INotifyPropertyChanged örneğin uzatma yöntemleri yarattı. Aslında, zayıf olay işleme için gerçekten anonim yöntemler kullanamazsınız. (Doğru bir şekilde anladığım takdirde, derleyici, işleyiciye sahip olan bir 'kapatma sınıfı' oluşturur (başvurulan değerleri tutturmak için), ancak kapatma sınıfınız herhangi bir yerde referans alınmadığından, GC bunu temizler ve olay işleyicisi # 1: Bu doğru mu? Demek istediğim doğrudur, daha sonra zayıf bir olay işleyicisi için anonim bir yöntem (veya lambda) kullanıldığında, işleyici yalnızca GC bu sırada çalışmadığı zaman çağrılır (örn. Bu belirsizdir)?
Eh, öyle yaptım, bu yüzden doğru yaptığından emin olmak için bazı birim testleri yaptım. i aşağıdaki birim testi çarpana kadar bu yolunda görünüyordu:
class DidRun
{
public bool Value { get; set; }
}
class TestEventPublisher
{
public event EventHandler<EventArgs> MyEvent;
public void RaiseMyEvent()
{
if (MyEvent != null)
MyEvent(this, EventArgs.Empty);
}
}
class TestClosure
{
public DidRun didRun { get; set; }
public EventHandler<EventArgs> Handler { get; private set; }
public TestClosure()
{
this.Handler = new EventHandler<EventArgs>((s, e) => didRun.Value = true);
}
}
[TestMethod]
public void TestWeakReference()
{
var raiser = new TestEventPublisher();
var didrun = new DidRun();
var closure = new TestClosure { didRun = didrun };
WeakEventManager<TestEventPublisher, EventArgs>.AddHandler(raiser, "MyEvent", closure.Handler);
closure = null;
GC.Collect();
GC.Collect();
raiser.RaiseMyEvent();
Assert.AreEqual(false, didrun.Value);
}
Soru 2: herkes neden bu test başarısız oluyor benim açıklayabilir misiniz?
Beklenti: Burada herhangi bir kapanış yok (onları dışarı çıkardım, ne olduğundan emin olmak için), WeakEventManager ile bir etkinliğe abone olan bir nesne (kapama) var ve sonra ona referans (closure = null;).
Eski kapatma sınıfımı temizlemek için 2 GC.Collect() çağrısını bekliyordum, bu nedenle WeakEventManager aboneyi düşürür ve işleyiciyi çalıştırmaz, ancak sınama başarısız olur. Herhangi bir fikir?
DÜZENLEME: şimdi onlar
vay, sayesinde bir çok ve gerçekten ı değerinde geçirilen işleyicisine sabit referans olduğu, ardı A
ConditionalWeakTable
bu için çalışması gerekir. Şimdi anladım. Yardımlarınız için tekrar teşekkürler! – MBoros