none
Events, Publisher lives much longer than subscriber RRS feed

  • Question

  • Hello,

    I have the problem, that I have a relatively long lived class where an event is defined in a class (the publisher), let's call class P. A subscriber class (say class S) requires an event from the publisher P when a property has changed (The user can modify a property of class P). However, the subscriber S is relatively short lived. The subscriber would be called 1000's of times from the user, where each object of class S has a reference to the same publisher class P. The issue is, the publisher keeps a reference of (all) the subscriber(s), so it won't be garbage collected, the event remains, and although the publisher class P's object is now out of scope, it now wastes time having an event called when it's no longer needed (1000's of delegates are then called).

    I don't wish to use the IDispose interface on the subscriber class S, it feels kludgy. The subscriber class S doesn't expose events itself, so the user of the subscriber class wouldn't really understand why, when we don't use files, databases, unmanaged resources, etc. why an IDispose interface is needed. What I would find really nice is to allow an object of class P to fall out of scope and to be garbage collected automatically, even though S holds a reference. Class P would be notified somehow and clean itself up

    I've tried to understand the post here http://social.msdn.microsoft.com/forums/en-us/clr/thread/32508CA3-ACC9-45EC-B9AB-7FE375123A69

    I can't say I understand the accepted answer, nor am I sure that this might be my solution. There's some reference of Weak References, not sure if this can help, or what the advantages/disadvantages are, and how much work or overhead it has.

    Thanks in advance,

    Jason.

    Thursday, January 20, 2011 9:49 PM

Answers

  • What you need are Weak Events.

     

    There is an entire MSDN section on Weak Event Patterns.  It walks through how to implement them using WeakEventManager.  This class, internally, uses WeakReferences to keep a reference to the object without keeping it from being garbage collected.

     

    This pattern is used extensively throughout WPF, since it is very easy for control authors to run into this situation.  The main downside, though, is that you can't use "standard" C# events anymore, since you have to register for the event slightly differently.  However, in a situation like yours, it works around the problem of effectively creating a memory leak.

     

     

     


    Reed Copsey, Jr. - http://reedcopsey.com
    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".
    • Marked as answer by Jason Curl Friday, January 21, 2011 8:15 PM
    Friday, January 21, 2011 1:59 AM
    Moderator

All replies

  • What you need are Weak Events.

     

    There is an entire MSDN section on Weak Event Patterns.  It walks through how to implement them using WeakEventManager.  This class, internally, uses WeakReferences to keep a reference to the object without keeping it from being garbage collected.

     

    This pattern is used extensively throughout WPF, since it is very easy for control authors to run into this situation.  The main downside, though, is that you can't use "standard" C# events anymore, since you have to register for the event slightly differently.  However, in a situation like yours, it works around the problem of effectively creating a memory leak.

     

     

     


    Reed Copsey, Jr. - http://reedcopsey.com
    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".
    • Marked as answer by Jason Curl Friday, January 21, 2011 8:15 PM
    Friday, January 21, 2011 1:59 AM
    Moderator
  • It wasn't obvious in the documentation from Microsoft how deterministic the behaviour of WeakEvents are, if my object falls out of scope and there are no more hard references to my object (only weak references through the documentation by Microsoft), is it guaranteed to no longer receive events?

     

    e.g. I instantiate three objects that have weak references to a publisher. I do it as so, where the constructor of MyClassS(P) registers for notification with object P.:

    MyClassP P = new MyClassP();

    MyClassS S = new MyClassS(P);

    MyClassS S = new MyClassS(P);

    MyClassS S = new MyClassS(P);

    P.Notify();

    will P.Notify() raise events three times, or only once - the to the last live reference?

    Friday, January 21, 2011 9:43 PM
  • It wasn't obvious in the documentation from Microsoft how deterministic the behaviour of WeakEvents are, if my object falls out of scope and there are no more hard references to my object (only weak references through the documentation by Microsoft), is it guaranteed to no longer receive events?

     

    e.g. I instantiate three objects that have weak references to a publisher. I do it as so, where the constructor of MyClassS(P) registers for notification with object P.:

    MyClassP P = new MyClassP();

    MyClassS S = new MyClassS(P);

    MyClassS S = new MyClassS(P);

    MyClassS S = new MyClassS(P);

    P.Notify();

    will P.Notify() raise events three times, or only once - the to the last live reference?

    It will raise events anywhere from 1-3 times.  It's indeterminant.  (However, you have to remove the MyClassS declaration from the third&fourth line before it compiles ;) ).

     

    WeakEvent works by using a WeakReference.  This doesn't cause the object to be collected, but rather prevents it from remaining rooted.  The GC will, at some point, find it and clean it up.  Until that happens, though, the object still exists, and will still receive notifications.

     

    If you require firm, deterministic unsubscription, the WeakEvent pattern won't get you there.  You'll need to use IDisposable and have the Dispose() method unsubscribe, or some other form.  WeakEvents just prevent the object from staying rooted and alive...

     

     


    Reed Copsey, Jr. - http://reedcopsey.com
    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".
    Friday, January 21, 2011 10:51 PM
    Moderator