Subscribing to Events Published by the Singleton Class

I have a Singleton class named CacheState. This class publishes many events. CacheState has System.Timers.Timer that loops around and fires all these events.

Then in my asp.net application I subscribe to these events during Application_Start. The timer in CacheState also starts during this time:

protected void Application_Start(object sender, EventArgs e)
        {           
                CacheState.Instance.ProductChangedEvent += (objSender, argsE) => ProductService.ReloadProductCache(false);
                CacheState.Instance.PageflexChangedEvent += (objSender, argsE) => ProductService.ResetPageflexCache(false);
                CacheState.Instance.DeliveryChangedEvent += (objSender, argsE) => PricingRuleService.ResetDeliveryMethodsCache(false);
                CacheState.Instance.UIItemChangedEvent += (objSender, argsE) => TemplateService.ResetUIItemsCache(false);
                CacheState.Instance.ProductAttributeChangedEvent += Instance_ProductAttributeChangedEvent;
                CacheState.Instance.Start();

        }

      

I read that C # events can cause memory leaks. So, can anyone tell me if I am doing it wrong?

Thank.

0


source to share


3 answers


A singleton instance contains references to all objects that have subscribed to its events. If these objects do not live as long as a single instance and they do not unsubscribe from these events, they will remain in memory. This is the only time you experience a memory leak. Obviously, if the event source is removed before your listeners, the link will be cleared, and if you unregister your listeners properly, then there will be no references left either.

To solve this problem you can implement the Weak Event Pattern or implement eg. IDisposable

in all objects that listen for solid color events and make sure they are positioned correctly in your code!



Of course, this is not only for single objects, but for any object that acts as an event source. The singleton event source is especially dangerous, however, as it usually lives as long as your application is running, and thus lives at least as long as any other object.

+5


source


C # can cause a memory leak if you assign an event through your code more than once. This can happen in complex codes and often with newbies. And because of this, your event handler will be executed more than once.

The correct way to avoid this is to detach the event (- =) before attaching it (+ =), the best would be to encapsulate in a method that controls it.

This ensures that the event stack of pointers to the event-handling method is filled with exactly one entry (if needed).



This is one thing I know about memory leaks.

Links are another matter. If your event handler accesses a global object or a list of globals and inserts values, and you are not tracking, the event handler will cause the global variable to be instantiated, used, referenced, and so on. But it depends on the design.

If anyone knows more I would appreciate it.

0


source


    // generic delegate for genric events
public delegate void EventsHandler<in TArgs>(TArgs args) where TArgs : EventArgs;

// generic singleton
public abstract class EventsBase<TEvents> where TEvents : class, new()
{
    private static readonly object lockObject = new object();

    private static volatile TEvents instance;

    public static TEvents Instance
    {
        get
        {
            if (instance == null)
            {
                lock (lockObject)
                {
                    if (instance == null)
                    {
                        instance = new TEvents();
                    }
                }
            }
            return instance;
        }
    }
}

public class EventArgs<T> : EventArgs
{
    public T Item { get; set; }

    public EventArgs(T item)
    {
        Item = item;
    }
}

public class MyEvents : EventsBase<MyEvents>
{

    public event EventsHandler<EventArgs<IList<int>>> OnCheckedDataBase;
    public event EventsHandler<EventArgs<IList<int>>> OnProcessedData;

    public void CheckedDataBase(IList<int> handler)
    {
        if (OnCheckedDataBase != null)
        {
            OnCheckedDataBase(new EventArgs<IList<int>>(handler));
        }
    }
    public void ProcessedData(IList<int> handler)
    {
        if (OnProcessedData != null)
        {
            OnProcessedData(new EventArgs<IList<int>>(handler));
        }
    }

 }

MyEvents.Instance.OnCheckedDataBase += OnCheckedDataBase; //register

MyEvents.Instance.CheckedDataBase(this);  //fire

      

0


source







All Articles