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 7892313
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 3, 20262026-06-03T06:50:21+00:00 2026-06-03T06:50:21+00:00

I was trying to save time by developing a generic weak event listener that

  • 0

I was trying to save time by developing a generic weak event listener that I could just pass in an Action to take. Things seem to work fine until one is unregistered. This seems to unregister them all. The thing I am confused about is why, and how is this different then passinging in this for the IWeakEventListener parameter?

  public class GenericWeakEventListener : IWeakEventListener
  {
    #region EventAction

    /// <summary>
    /// Action to take for the event
    /// </summary>
    private Action<Type, object, EventArgs> _eventAction;

    /// <summary>
    /// Gets or sets the action to take for the event
    /// </summary>
    //[DataMember]
    public Action<Type, object, EventArgs> EventAction
    {
      get
      {
        return _eventAction;
      }

      private set
      {
        if (EventAction != value)
        {
          _eventAction = value;
        }
      }
    }

    #endregion EventAction

    #region Constructors

    public GenericWeakEventListener(Action<Type, object, EventArgs> action)
    {
      EventAction = action;
    }

    #endregion Constructors

    #region Public Methods

    public bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
    {
      if (EventAction != null)
      {
        EventAction(managerType, sender, e);
      }

      return true;
    }

    #endregion Public Methods
  }

EDIT:

This is the listener code:

  public class SomeClient
  {
    public int ID { get; set; }

    private Timer timer = null;
    private Timer timer2 = null;

    public SomeClient(int id, SomeService service)
    {
      ID = id;
      //EventHandler<GenericEventArgs<string>> d = (o, s) => Console.WriteLine("Client {0}: {1}", ID, s.Item);
      if (service != null) SomeEventChangedEventManager.AddListener(service, new GenericWeakEventListener((t, s, e) => { Console.WriteLine("SomeEvent: " + ID); }));

      timer = new Timer { AutoReset = true, Interval = 1000 };
      SomeTimerElapsedEventManager.AddListener(timer, new GenericWeakEventListener((t, s, e) => { Console.WriteLine("SomeTimer: " + ID); }));
      timer.Start();
    }
  }

This is the code from the publisher:

  public class SomeService
  {
    public event EventHandler<GenericEventArgs<string>> SomeEvent;

    public SomeService()
    {
      System.Timers.Timer timer = new Timer { AutoReset = true, Interval = 1000 };
      timer.Elapsed += (sender, args) => { if (SomeEvent != null) SomeEvent(this, new GenericEventArgs<string>(Guid.NewGuid().ToString())); };
      timer.Start();
    }
  }

This is the code from the main method:

public static void Main(string[] args)
{
  SomeService service = new SomeService();
  List<SomeClient> clients = new List<SomeClient>();

  // Build clients
  for (int x = 0; x < 5; x++)
  {
    clients.Add(new SomeClient(x + 1, service));
  }

  System.Timers.Timer timer = new Timer { AutoReset = true, Interval = 5000 };
  timer.Elapsed += (s, a) =>
    {
      if (clients.Count == 0)
      {
        return;
      }

      Console.WriteLine("Removing\r\n");
      clients.RemoveAt(0);
      GC.Collect();
    };
  timer.Start();

  Console.ReadLine();
}

This is the output:
SomeEvent: 1
SomeEvent: 2
SomeEvent: 3
SomeEvent: 4
SomeEvent: 5
SomeTimer: 2
SomeTimer: 3
SomeTimer: 4
SomeTimer: 1
SomeTimer: 5
SomeEvent: 1
SomeEvent: 2
SomeEvent: 3
SomeEvent: 4
SomeEvent: 5
SomeTimer: 1
SomeTimer: 2
SomeTimer: 3
SomeTimer: 4
SomeTimer: 5
SomeEvent: 1
SomeEvent: 2
SomeEvent: 3
SomeEvent: 4
SomeEvent: 5
SomeTimer: 2
SomeTimer: 3
SomeTimer: 4
SomeTimer: 5
SomeTimer: 1
SomeEvent: 1
SomeEvent: 2
SomeEvent: 3
SomeEvent: 4
SomeEvent: 5
SomeTimer: 1
SomeTimer: 2
SomeTimer: 3
SomeTimer: 5
SomeTimer: 4
SomeEvent: 1
SomeEvent: 2
SomeEvent: 3
SomeEvent: 4
SomeEvent: 5
Removing

Without the generic weak event listener then output continues on without 1 and then without 2 and so on.

  • 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-03T06:50:22+00:00Added an answer on June 3, 2026 at 6:50 am

    EDIT FROM OP EDIT: Got it. Here’s what I think is happening:

    You are declaring a lambda owned by SomeClient and containing an external closure to the instance variable ID. That makes the lambda, which is passed as a delegate to the event on SomeService via the SomeEventChangedEventManager, dependent on the continued existence of that instance of ID.

    When you remove that SomeClient instance, the ID variable required by that lambda goes out of scope and is GCed. However, I don’t see any part of this code that removes this lambda from the handlers of SomeService’s SomeEvent. So, the lambda remains in memory as a reference to the anonymous delegate, but other data that it depends on is now gone. This causes an exception to be thrown by the runtime, which is somehow getting swallowed and is not causing the entire program to blow up.

    But, the event, which basically executes handler delegates in the order they were attached (this is an implementation detail that they generally tell you to ignore) has stopped execution because one of the handlers has thrown out. This makes it appear that removing the first client has removed all of them, when in fact those clients’ handlers are just not executed because the first handler errored.

    The fix is twofold:

    • Define the lambda and store it as an instance variable of SomeClient. This allows you to keep a reference to it, which is important because delegates are not compared semantically when determining equality, so the following code doesn’t work:

      SomeEvent += (a,b,c) => Foo(a,b,c);
      //the following line will not remove the handler added in the previous line,
      //because the two lambdas are compiled into differently-named methods
      //and so this is a different reference to a different method.
      SomeEvent -= (a,b,c) => Foo(a,b,c);
      
    • Implement IDisposable, and/or a finalizer, on SomeClient. When removing the client from the list, the disposer/finalizer, called by the GC, should remove this instance’s lambda from the SomeEvent listeners (probably through a RemoveListener() method on the Manager). Because you kept a reference to the delegate that points at exactly what was added, the handler will be removed, and so won’t be executed and won’t error out.

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

Sidebar

Related Questions

Ok, I'm trying to save some time creating some generic classes to draw objects
I'm just trying to save time by not learning about IIS and WAS, so
Recently I've been trying to save on render time by minimizing the amount of
I'm trying to save myself some coding time by taking advantage of using namespace
I'm having hard time trying to figure out how to auto-save user data in
When trying to save the database using boost serialization, I encounter the segfault that
I am trying to save the time in the database for when a user
I am trying to save image captured from web cam with current time.Like 06.06.2010
I've been trying to use AutoMapper to save some time going from my DTOs
I am trying to save the date of file parsing, so that when next

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.