Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8254389
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 8, 20262026-06-08T01:10:18+00:00 2026-06-08T01:10:18+00:00

EDIT: After Joel Coehoorns excellent answer, I understand that I need to be more

  • 0

EDIT: After Joel Coehoorns excellent answer, I understand that I need to be more specific, so I modified my code to be closer to thing I’m trying to understand…

Events: As I understand, in the background the events are “collection” of EventHandlers aka Delegates which will be executed when event raised. So for me it means that if object Y has event E and object X subscribes to event Y.E, then Y will have reference to X, since Y must execute the method located in X, in that way, X can not be collected, and that thing i understand.

//Creates reference to this (b) in a.
a.EventHappened += new EventHandler(this.HandleEvent);

But it is not what Joel Coehoorn tells…

However, there is an issue with events such that sometimes people like to use IDisposable with types that have events. The problem is that when a type X subscribes to events in another type Y, X now has a reference to Y. This reference will prevent Y from being collected.

I not understand how X will reference the Y ???

I modified a bit my example to illustrate my case more closer:

class Service //Let's say it's windows service that must be 24/7 online
{       
    A _a;

    void Start()
    {
       CustomNotificationSystem.OnEventRaised += new EventHandler(CustomNotificationSystemHandler)
       _a = new A();

       B b1 = new B(_a);
       B b2 = new B(_a);
       C c1 = new C(_a);
       C c2 = new C(_a);
    }

    void CustomNotificationSystemHandler(args)
    {

        //_a.Dispose(); ADDED BY **EDIT 2***
        a.Dispose();

        _a = new A();
        /*
        b1,b2,c1,c2 will continue to exists as is, and I know they will now subscribed
        to previous instance of _a, and it's OK by me, BUT in that example, now, nobody
        references the previous instance of _a (b not holds reference to _a) and by my
        theory, previous instance of _a, now may be collected...or I'm missing
        something???
        */
    }

}  

class A : IDisposable
        {
           public event EventHandler EventHappened;
        }

        class B
        {          
           public B(A a) //Class B does not stores reference to a internally.
           {
              a.EventHappened += new EventHandler(this.HandleEventB);
           }

           public void HandleEventB(object sender, EventArgs args)
           {
           }
        }

        class C
        {          
           public C(A a) //Class B not stores reference to a internally.
           {
              a.EventHappened += new EventHandler(this.HandleEventC);
           }

           public void HandleEventC(object sender, EventArgs args)
           {
           }
        }

EDIT 2: OK, now it’s clear, when subscriber subscribes to a publishers events, it’s NOT creates a reference to the publisher in subscriber. Only the reference from publisher to subscriber created (through EventHandler)…in this case when publisher collected by GC before the subscriber (subscribers lifetime is greater then publishers), there’s no problem.

BUT…as I know, it’s not guaranteed when GC will collect the publisher so in theory, even if subscribers lifetime is greater then publishers, it can happen that subscriber is legal for collection, but publisher is still not collected (I don’t know if within closest GC cycle, GC will be smart enough to collect publisher first and then subscriber.

Anyway, in such case, since my subscriber do not have direct reference to publisher and can’t unsubscribe the event, I would like to make publisher to implement IDisposable, in order to dispose it before delete all references to him (see in CustomNotificationSystemHandler in my example).

AND AGAIN What I should write in publishers dispose method in order to clear all references to subscribers? should it be EventHappened -= null; or EventHappened = null; or there’s no way to do it in such way, and I need to make something like below ???

public event EventHandler EventHappened
   {
      add 
      {
         eventTable["EventHappened"] = (EventHandler)eventTable["EventHappened"] + value;
      }
      remove
      {
         eventTable["EventHappened"] = (EventHandler)eventTable["EventHappened"] - value; 
      }
   }
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-08T01:10:20+00:00Added an answer on June 8, 2026 at 1:10 am

    I have added My comments in your sample code.

    class A : IDisposable
    {
       public event EventHandler EventHappened
       {
          add 
          {
             eventTable["EventHappened"] = (EventHandler)eventTable["EventHappened"] + value;
          }
          remove
          {
             eventTable["EventHappened"] = (EventHandler)eventTable["EventHappened"] - value; 
          }
       }
    
       public void Dispose()
       {
          //Amit: If you have only one event 'EventHappened', 
          //you can clear up the subscribers as follows
    
          eventTable["EventHappened"] = null;
    
          //Amit: EventHappened = null will not work here as it is 
          //just a syntactical sugar to clear the compiler generated backing delegate.
          //Since you have added 'add' and 'remove' there is no compiler generated 
          //delegate to clear
          //
          //Above was just to explain the concept.
          //If eventTable is a dictionary of EventHandlers
          //You can simply call 'clear' on it.
          //This will work even if there are more events like EventHappened          
       }
    }
    
    class B
    {          
       public B(A a)
       {
          a.EventHappened += new EventHandler(this.HandleEventB);
    
          //You are absolutely right here.
          //class B does not store any reference to A
          //Subscribing an event does not add any reference to publisher
          //Here all you are doing is calling 'Add' method of 'EventHappened'
          //passing it a delegate which holds a reference to B.
          //Hence there is a path from A to B but not reverse.
       }
    
       public void HandleEventB(object sender, EventArgs args)
       {
       }
    }
    
    class C
    {          
       public C(A a)
       {
          a.EventHappened += new EventHandler(this.HandleEventC);
       }
    
       public void HandleEventC(object sender, EventArgs args)
       {
       }
    }
    
    class Service
    {       
        A _a;
    
        void Start()
        {
           CustomNotificationSystem.OnEventRaised += new EventHandler(CustomNotificationSystemHandler)
    
           _a = new A();
    
           //Amit:You are right all these do not store any reference to _a
           B b1 = new B(_a);
           B b2 = new B(_a);
           C c1 = new C(_a);
           C c2 = new C(_a);
        }
    
        void CustomNotificationSystemHandler(args)
        {
    
            //Amit: You decide that _a has lived its life and must be disposed.
            //Here I assume you want to dispose so that it stops firing its events
            //More on this later
            _a.Dispose();
    
            //Amit: Now _a points to a brand new A and hence previous instance 
            //is eligible for collection since there are no active references to 
            //previous _a now
            _a = new A();
        }    
    }
    

    b1,b2,c1,c2 will continue to exists as is, and I know they will now
    subscribed to previous instance of _a, and it’s OK by me, BUT in that
    example, now, nobody references the previous instance of _a (b not
    holds reference to _a) and by my theory, previous instance of _a, now
    may be collected…or I’m missing something???

    As explained through my comments in the above code, you are not missing anything here 🙂

    BUT…as I know, it’s not guaranteed when GC will collect the
    publisher so in theory, even if subscribers lifetime is greater then
    publishers, it can happen that subscriber is legal for collection, but
    publisher is still not collected (I don’t know if within closest GC
    cycle, GC will be smart enough to collect publisher first and then
    subscriber.

    Since publisher references subscriber, it can never happen that the subscriber becomes eligible for collection before the publisher but reverse can be true. If publisher gets collected before subscriber then, as you said, there is no problem. If the subscriber belongs to a lower GC generation than publisher then since publisher holds a reference to subscriber, GC will treat the subscriber as reachable and will not collect it. If both belong to same generation, they will be collected together.

    since my subscriber do not have direct reference to publisher and
    can’t unsubscribe the event, I would like to make publisher to
    implement IDisposable

    Contrary to what some have suggested, I would recommend implementing dispose if at any point you are deterministically sure that the object is no longer required. Simply updating an object reference may not always lead to an object stop publishing events.

    Consider the following code:

    class MainClass
    {
        public static Publisher Publisher;
    
        static void Main()
        {
            Publisher = new Publisher();
    
            Thread eventThread = new Thread(DoWork);
            eventThread.Start();
    
            Publisher.StartPublishing(); //Keep on firing events
        }
    
        static void DoWork()
        {
            var subscriber = new Subscriber();
            subscriber = null; 
            //Subscriber is referenced by publisher's SomeEvent only
            Thread.Sleep(200);
            //We have waited enough, we don't require the Publisher now
            Publisher = null;
            GC.Collect();
            //Even after GC.Collect, publisher is not collected even when we have set Publisher to null
            //This is because 'StartPublishing' method is under execution at this point of time
            //which means it is implicitly reachable from Main Thread's stack (through 'this' pointer)
            //This also means that subscriber remain alive
            //Even when we intended the Publisher to stop publishing, it will keep firing events due to somewhat 'hidden' reference to it from Main Thread!!!!
        }
    }
    
    internal class Publisher
    {
        public void StartPublishing()
        {
            Thread.Sleep(100);
            InvokeSomeEvent(null);
            Thread.Sleep(100);
            InvokeSomeEvent(null);
            Thread.Sleep(100);
            InvokeSomeEvent(null);
            Thread.Sleep(100);
            InvokeSomeEvent(null);
        }
    
        public event EventHandler SomeEvent;
    
        public void InvokeSomeEvent(object e)
        {
            EventHandler handler = SomeEvent;
            if (handler != null)
            {
                handler(this, null);
            }
        }
    
        ~Publisher()
        {
            Console.WriteLine("I am never Printed");
        }
    }
    
    internal class Subscriber
    {
        public Subscriber()
        {
            if(MainClass.Publisher != null)
            {
                MainClass.Publisher.SomeEvent += PublisherSomeEvent;
            }
        }
    
        void PublisherSomeEvent(object sender, EventArgs e)
        {
            if (MainClass.Publisher == null)
            {
                //How can null fire an event!!! Raise Exception
                throw new Exception("Booooooooommmm");
                //But notice 'sender' is not null
            }
        }
    }
    

    If you run the above code, more often than not you will receive the ‘Booooooooommmm’. Hence idea is that event publisher must stop firing events when we are sure that its life is up.

    This can be done through Dispose method.

    There are two ways to achieve this:

    1. Set a flag ‘IsDisposed’ and check it before firing any event.
    2. Clear up the event subscribers list (as suggested in my comments in your code).

    Benefit of 2 is that you release any reference to the subscribers, thereby enabling there collection (as I explained earlier even if the publisher is garbage but belongs to higher generation then it may still prolong collection of lower generation subscribers).

    Though, admittedly, it will be quite rare that you experience the demonstrated behavior due to ‘hidden’ reachability of the publisher but as you can see benefits of 2 are clear and are valid for all event publishers especially long living ones (Singletons anybody!!!). This itself makes it worth to implement Dispose and go with 2.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

FINAL EDIT: After following the answer from Darin Dimitrov, I have found that the
EDIT After some more research I found that I cannot use a continuous form
EDIT: After I modified the web.config and I don't get error that's good.... then
Possible Duplicate: Saving changes after table edit in SQL Server Management Studio I need
oo design basics here... Edit: To clarify after first answer - I'm not asking
EDIT: a few weeks after I posted this question Evan Coury wrote an excellent
EDIT: My mistake was that I had a go after the first select statement
EDIT: This post was originally specific to ASP.NET, but after thinking about it I'm
[EDIT] I am changing this to more concisely explain what my problem was, after
Edit: After reading the responses, I believe the answer is don't do this, hence

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.