4

Playing with weak event

public class Test
{
    public Test(Button button)
    {
        WeakEventManager<Button, RoutedEventArgs>.AddHandler(button, nameof(Button.Click),
            (s, e) => MessageBox.Show("Tada"));
    }
}

with this code

Test _test;
void ButtonCreate_Click(object sender, RoutedEventArgs e) => _test = new Test(button);
void ButtonDelete_Click(object sender, RoutedEventArgs e) => _test = null;
void ButtonGC_Click(object sender, RoutedEventArgs e)
{
    GC.Collect(2);
    GC.WaitForPendingFinalizers();
}

It looks like this event handler life time is longer than I'd expect.

Here is a demo where I click Create 3 times, then Delete and GC, but clicking the button will still execute all event handlers:

My question is what is wrong here?


Without lambda there is no such issue

public class Test
{
    public Test(Button button)
    {
        WeakEventManager<Button, RoutedEventArgs>.AddHandler(button,
            nameof(Button.Click), Button_Click);
    }
    void Button_Click(object sender, RoutedEventArgs e) => MessageBox.Show("Tada");
}

but another problem arise, where event handler is still called after Delete unless GC is pressed!

Community
  • 1
  • 1
Sinatr
  • 20,892
  • 15
  • 90
  • 319
  • Are you expecting setting `_test` to `null` to remove the event handler? – stuartd May 10 '17 at 13:00
  • @stuartd, don't forget `GC.Collect()`. I expect object to be garbage collected and then event handler shouldn't be called. Am I wrong? – Sinatr May 10 '17 at 13:04
  • The point of a weak event is to prevent an event subscription from keeping the event source alive. Add a finalizer to Test, like ~Test() => System.Diagnostics.Debug.WriteLine("the end"); and you'll see the Test instances expire when you call GC.Collect(). The lambda doesn't need the Test instance to do its job and the button is alive throughout the test so you are not actually testing the usefulness of a weak event. – Hans Passant May 10 '17 at 14:38
  • @HansPassant, I've added finalizer and I see it runs after `GC.Collect()`, but the event handler is still **when using lambda**, therefore my new question.. I didn't though what using weak event will have such effect, where "ready to be disposed" object (no references) required explicit garbage collection, otherwise event handler keeps running, but that's [another question](http://stackoverflow.com/q/43890059/1997232). Here, I'd like only to understand what is wrong when using lambda. – Sinatr May 11 '17 at 06:58

0 Answers0