Note that there are some explanatory texts on larger screens.

plurals
  1. POWeakEventManager holds reference to subscriber
    primarykey
    data
    text
    <p>I have been using WeakEventManager to avoid memory leaks, and i started to overuse them. I created extension methods for example for the INotifyPropertyChanged like:</p> <pre><code> public static void AddWeakPropertyChanged(this INotifyPropertyChanged item, Action handler) { PropertyChangedEventManager.AddHandler(item, (s, e) => handler(e.PropertyName), string.Empty); } </code></pre> <p>Now i quickly realized, that this doesn't work. In fact, you can't really use anonymous methods for weak event handling. (If i understand correctly, then the compiler creates a 'closure class' for it (to hold referenced values), which has the handler, but since your closure class is not referenced anywhere, the GC will clear it away, and the event handler will not be called)</p> <p>Question #1: Is that correct? I mean is it correct, then when using an anonymous method (or lambda) for a weak event handler, the handler is called only if the GC did not run in the meanwhile (e.g. it is undeterministic)?</p> <p>Well, i thaught so, so i did some unit tests to make sure i get it right. It seemed allright until i hit the following unit test:</p> <pre><code> class DidRun { public bool Value { get; set; } } class TestEventPublisher { public event EventHandler&lt;EventArgs&gt; MyEvent; public void RaiseMyEvent() { if (MyEvent != null) MyEvent(this, EventArgs.Empty); } } class TestClosure { public DidRun didRun { get; set; } public EventHandler&lt;EventArgs&gt; Handler { get; private set; } public TestClosure() { this.Handler = new EventHandler&lt;EventArgs&gt;((s, e) => didRun.Value = true); } } [TestMethod] public void TestWeakReference() { var raiser = new TestEventPublisher(); var didrun = new DidRun(); var closure = new TestClosure { didRun = didrun }; WeakEventManager&lt;TestEventPublisher, EventArgs&gt;.AddHandler(raiser, "MyEvent", closure.Handler); closure = null; GC.Collect(); GC.Collect(); raiser.RaiseMyEvent(); Assert.AreEqual(false, didrun.Value); } </code></pre> <p>Question #2: Can anyone explain my why does this test fail?</p> <p>Expectation: Here i do not have any closures (i took them out, to make sure what is happening), i simply have an object (closure), that subscribes to an event with the WeakEventManager, and then i drop the reference to it (closure = null;).</p> <p>I was expecting the 2 GC.Collect() calls, to clean up my old closure class, so the WeakEventManager would drop the subscriber, and not run the handler, but the test fails. Any ideas?</p> <p>EDIT: Sorry, the generic arguments were not visible, now they are</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload