For work, I have to subscribe to an external event and handle it when it comes by. I have no problem doing all that but I noticed that after the first GC pass, the event handler I added seemingly gets removed. I won't be able to receive the next event after the collection.
If I manually trigger the GC then remove and add the handler, I will properly receive the next event.
I tried using KeepAlive and SuppressFinalize from the GC to no avail. I also tried to add the handler as a lambda, but it still gets removed after the first garbage collection.
example code (pseudo, for reference only)
private externalLibrary.Server server = new Server();
private externalLibrary.DataHandler handler; //delegate is assigned in constructor
public bool Subscribe(){
//...
server.Data.Received += handler;
}
With this setup, I receive events until the first GC.
My ugly workaround looks like this:
ResetHandler(){
server.Data.Received -= handler;//It seems to already be removed by GC but better be safe than sorry
server.Data.Received += handler;
}
And in the code when I finished my processing of the event, I do:
GC.Collect;
ResetHandler();
This allows me to circumvent the problem. I would like to find a better solution or know what I am doing wrong.
Please note that this is my very first question here.
Thank you for your input.
Related
Is this approach correct? I want only one subscription to this events. When I try using unsubscription -=, for some reason events are actually adding and every time it's more.PresentationViewModel is not disposed when closing associated window so I can't rely on IDisposable this time yet it is implemented and events are disposed there also - maybe an overkill.
I want to know if assigning null is going to bring any side effect I might not want.
Thank you.
public PresentationViewModel ViewModel
{
get
{
if (_viewModel != null) return _viewModel;
_viewModel = (PresentationViewModel) DataContext;
_viewModel.OnNavigatedToHandler = null; // <-------------------
_viewModel.OnNavigatedToHandler += OnNavigatedToHandler;
_viewModel.OnNavigatedFromHandler = null; // <-------------------
_viewModel.OnNavigatedFromHandler += OnNavigatedFromHandler;
return _viewModel;
}
}
And previously I added unsubscription this way which resulted in many calls of this methods:
_viewModel.OnNavigatedToHandler -= OnNavigatedToHandler;
_viewModel.OnNavigatedToHandler += OnNavigatedToHandler;
_viewModel.OnNavigatedFromHandler -= OnNavigatedFromHandler;
_viewModel.OnNavigatedFromHandler += OnNavigatedFromHandler;
Is this approach correct ... for some reason events are actually adding...
To prevent your event handler from being invoked when the event is raised, you need to
unsubscribe from the event. In order to help prevent any resource leaks, you should unsubscribe from events, read more here about this.
As for your comment about, for some reason events are actually adding, the reason for this is you are not unsubscribing and therefore the object is kept alive by this reference. In return, doing this without unsubscribing would create a memory leak.
As already mention in the comments, do not assign null to the event as, "it will unsubscribe ALL handlers, even ones that your code didn't subscribe." as Matthew Watson has pointed out. Jon Skeet notes, it'll effectively clear the list of subscribers, which means no handlers whatsoever are called at this point, Matthew Watson also mentions this in his comments.
With all this in mind, -= is the proper way of unsubscribing an event and should be used.
References:
How to subscribe to and unsubscribe from events c#
Should I unsubscribe from events
Whenever you add a delegate to an event handler, you should remove it later, right? So if you attach an anonymous method to an event, does this create an event handler leak since you can't later remove it? This code sample from http://msdn.microsoft.com/en-us/library/0yw3tz5k%28VS.80%29.aspx seems to imply that this an okay practice though.
// Create a handler for a click event
button1.Click += delegate(System.Object o, System.EventArgs e)
{ System.Windows.Forms.MessageBox.Show("Click!"); };
Is this really an okay practice?
Whenever you add a delegate to an event handler, you should remove it later, right?
Not necessarily, no. Often you want the event handler to stay valid for as long as the event itself can be raised - that's certainly very common with UIs.
Is this really an okay practice?
Absolutely, so long as you don't need to unhook the handler. Think about the point at which you'd unhook the event handler. If it's "when the form (or button, or whatever) is elegible for garbage collection" then what benefit is there in removing the handler? Just let it be garbage collected with the form...
Whenever you add a delegate to an event handler, you should remove it later, right?
Well, not always. There are two reasons why you'd want to remove an event handler that you're adding:
You're constantly adding handlers to the same instance that are short lived. If you didn't remove them then there would be more and more handlers added, when most of them aren't needed.
Your handler internally holds onto a reference to an object who's lifetime is much shorter than the lifetime of whatever object the event belongs to, and the event handler won't be (or can't be) called once that other object goes out of scope. Leaving the event handler attached will either force it to stay in memory longer than desired, or possibly result in using an object that's "stale" and shouldn't be used anymore. (For example, if the resource has already been disposed you don't want that event to fire anymore.)
The reason #2 is an issue is because of how Garbage Collection works in C#. It marks all objects that it can be 100% sure are in scope as "alive", and then follows everything that any of those "alive" objects reference as also being "alive" until it's followed every reference in every live object. Anything that was never marked as "alive" is then deemded "dead" and eligible for garbage collection.
When you have an event handler attached to an event that delegate contains two things, an instance of an object and a method to run on that object. That referenced object won't be able to be garbage collected until either:
The object with the event is no longer "alive".
You remove the event handler (i.e. the reference to) your delegate, allowing your object to be freed earlier.
That said, a significant percentage of cases don't apply to either of those, so there's no need to bother removing the event handlers.
As an example, I often see people removing event handlers just before the event object goes out of scope. That's pointless. If the object is out of scope there's no problem with it holding onto references to...whatever.
Now, if you are in one of those few situations in which you do need to unsubscribe the event handler, and you're using an anonymous method you need to...not. Just create a class that can make it a named method and use that.
Subscibing to event with anonymous method (or lambda expression) potentially can lead to memory leaks, but not in this case.
In this case compiler will generate an anonymous method inside current class and you don't have any memory related issues as long as your button will not live much longer than your object.
The use of inline anonymous delegates as event handlers does prevent those handlers being removed, as you stated. This can indeed cause problems, especially if the delegate comes from a different object. If you had a class A with a public event E, and E was subscribed to by a class B (that has no containing/contains relationship to A) attaching an anonymous handler H, H is technically a member of B, and so as long as it's referred to (by being attached to A's event), B won't be GCed. B's lifetime becomes tied to A's, and if you didn't want or expect that you now have a memory leak.
Now, that's not always a problem. If B contains A, or the other way around, then A and B's lifetimes are already tied together anyway; in your case, the button itself will very probably be disposed of before its containing control that attached the handler. Similarly, A and B could be long-lived objects (say, the program's main form and a data repository) and won't be GCed until the program terminates anyway. As long as you never have to care about a difference in lifetime between A and B, and you never need to detach H from E to stop exhibiting whatever behavior H has, then you can attach all the anonymous handlers you like.
I have a rather short question about anonymous event handlers:
This is the code that I have:
public void AddTestControl(Control ctrl)
{
ctrl.Disposed += (o, e) => { RemoveTestControl(ctrl); };
ctrl.SomeEvent += _Control_SomeEvent;
}
public void RemoveTestControl(Control ctrl)
{
ctrl.SomeEvent -= _Control_SomeEvent;
}
Is this code above fine, or should the code be rewritten in order to remove the Disposed Event Handler?
Something like this:
public void AddTestControl(Control ctrl)
{
ctrl.Disposed += _Control_Disposed;
ctrl.SomeEvent += _Control_SomeEvent;
}
public void RemoveTestControl(Control ctrl)
{
ctrl.Disposed -= _Control_Disposed;
ctrl.SomeEvent -= _Control_SomeEvent;
}
Generally, the only situation where you need to remove the event handlers from an object in order for it to be eligible for garbage collection is when the publisher object (the one defining the event) lives longer than the subscriber object (the one containing the event handlers). In such a situation the GC won't be able to release the subscriber when it goes out of scope since it's still being referenced by the publisher.
In this case, assuming this is WebForms or WinForms, the publisher (that is the Control object), is most likely a child object of the subscriber (probably a Page or a Form), which will be the first to go out of scope taking all its associated objects with it. Hence there's no need to remove the event handlers.
It always feels cleaner to me to unsubscribe from events, even in situations where I know the subscribers always outlive the publisher (the object raising the event): the event will never be raised again, the publisher is no longer reachable and can be collected.
Then again, how many people go to the trouble of unsubscribing every event handler in e.g. a WinForms application? The object references point from the publisher to the subscribers, not the other way around, so the publisher can be collected while the subscribers live on. It doesn't present the same danger as the opposite situation, where a long-lived publisher (e.g. a static event) can wastefully keep potentially large subscribers alive long after they could have been collected.
If you want/need to unsubscribe, then the requirement to unsubscribe the same delegate makes anonymous event handlers a bit of a pain. The Reactive Extensions solve this problem in a neat way: rather than having to remember the delegate you subscribed, subscribing returns an IDisposable which unsubscribes when disposed. Chucking all your subscriptions into a CompositeDisposable lets you unsubscribe everything with just one Dispose call.
Both codez are fine, but I like second as a matter of personal preference. It reads clearer than the first.
On top of it with the first code, there's anonymous lambda delegate and it gets a current reference to ctrl. That code may behave unexpectedly depending on situation and compile optimisation settings: whether or not the call is inlined or not.
Not to mention that there's architectural problem with the code: you have ControlOwner and a bunch of Child Controls. I take it you're adding child controls to ControlOwner at runtime, and then trying to react to their behavivour by subscribing ControlOwner to the childControl events. This is fine for events like _ButtonClicked etc. But not good for Dispose. Let the child control handle it's disposing on itself, the OwnerControl doesn't need to know about it. Not to mention that it may not exist at a time ChildControl[n].Dispose is called.
In short:
* it is better to leave dispose event on ChildControl alone and do all clean up in ChildControl.Dispose
* it is not necessary to unsubscribe from events. Event dispatcher will check if subscriber is alive.
This question already has answers here:
Is it bad to not unregister event handlers?
(2 answers)
Closed 9 years ago.
I have 3 questions concerning events:
Should I always unsubscribe events that were subscribed?
What happens if I do NOT?
In the below examples, how would you unsubscribe from the subscribed events?
I have for example this code:
Ctor: Purpose: For database property updates
this.PropertyChanged += (o, e) =>
{
switch (e.PropertyName)
{
case "FirstName": break;
case "LastName": break;
}
};
and this: Purpose: For GUI-binding wrap the model into viewmodels
ObservableCollection<Period> periods = _lpRepo.GetDailyLessonPlanner(data.DailyDate);
PeriodListViewModel = new ObservableCollection<PeriodViewModel>();
foreach (Period period in periods)
{
PeriodViewModel periodViewModel = new PeriodViewModel(period,_lpRepo);
foreach (DocumentListViewModel documentListViewModel in periodViewModel.DocumentViewModelList)
{
documentListViewModel.DeleteDocumentDelegate += new Action<List<Document>>(OnDeleteDocument);
documentListViewModel.AddDocumentDelegate += new Action(OnAddDocument);
documentListViewModel.OpenDocumentDelegate += new Action<int, string>(OnOpenDocument);
}
PeriodListViewModel.Add(periodViewModel);
}
Well, let's take the last question first. You can't reliably unsubscribe from an event that you've subscribed to directly with a lambda expression. You either need to keep a variable around with the delegate in (so you can still use a lambda expression) or you need to use a method group conversion instead.
Now as for whether you actually need to unsubscribe, it depends on the relationship between the event producer and the event consumer. If the event producer should live for longer than the event consumer, you should unsubscribe - because otherwise the producer will have a reference to the consumer, keeping it alive for longer than it should be. The event handler will also keep getting called for as long as the producer produces it.
Now in many cases that's not a problem - for example, in a form the button that raises the Click event is likely to live for about as long as the form on which it's created, where the handler is typically subscribed... so there's no need to unsubscribe. This is very typical for a GUI.
Likewise if you create a WebClient solely for the purpose of a single asynchronous request, subscribe to the relevant event and start the asynchronous request, then the WebClient itself will be eligible for garbage collection when the request has finished (assuming you don't keep a reference elsewhere).
Basically, you should always consider the relationship between the producer and the consumer. If the producer is going to live longer than you want the consumer to, or it's going to continue raising the event after you're no longer interested in it, then you should unsubscribe.
1) It depends. Usually it's a good idea, but there are typical cases where you don't need to. Basically, if you are sure that the subscribing object is going to outlive the event source, you ought to unsubscribe, otherwise this would create an unnecessary reference.
If however your object is subscribing to its own events, like in the following:
<Window Loaded="self_Loaded" ...>...</Window>
--then you don't have to.
2) Subscribing to an event makes additional reference to the subscribing object. So if you don't unsubscribe, your object might be kept alive by this reference, making effectively a memory leak. By unsubscribing you are removing that reference. Note that in the case of self-subscription the problem doesn't arise.
3) You can do like that:
this.PropertyChanged += PropertyChangedHandler;
...
this.PropertyChanged -= PropertyChangedHandler;
where
void PropertyChangedHandler(object o, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case "FirstName": break;
case "LastName": break;
}
}
You don't have to desubscribe from an event when the instance that is subscribing has the same scope as the instance that is being subscribed to.
Lets say you are a form and you are subscribing to a control, these two together form a group. However, if you have a central class that manages forms and you have subscribed to the Closed event of that form, these do not form a group together and you must desubscribe once the form is closed.
Subscribing to an event makes the subscribed instance create a reference to the instance being subscribed to. This prevents garbage collection. So, when you have a central class that manages form instances, this will keep all forms in memory.
WPF is an exception because it has a weak event model where events are subscribed to using weak references and it will not hold the form in memory. However, it is still best practice to desubscribe when you are not part of the form.
You may take a look at this article on MSDN. Quote:
To prevent your event handler from
being invoked when the event is
raised, simply unsubscribe from the
event. In order to prevent resource
leaks, it is important to unsubscribe
from events before you dispose of a
subscriber object. Until you
unsubscribe from an event, the
multicast delegate that underlies the
event in the publishing object has a
reference to the delegate that
encapsulates the subscriber's event
handler. As long as the publishing
object holds that reference, your
subscriber object will not be garbage
collected.
1.) Should I always desubscribe events that were subscribed?
Usually yes. The only exception is when the object on which you subscribed isn't referenced anymore and will be garbage collected soon.
2.) What happens if I do NOT?
The object on which you subscribed will hold a reference to the delegate, which in turn holds a reference to its this pointer, and thus you'll get a memory leak.
Or if the handler was a lamda it will hold onto whatever local variables it bound, which thus won't be collected either.
Ok,
So I have a method which fires when someone clicks on our Icon in a silverlight application, seen below:
private void Logo_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
ShowInfo(true);
DispatcherTimer autoCloseTimer = new DispatcherTimer();
autoCloseTimer.Interval = new TimeSpan(0, 0, 10);
autoCloseTimer.Tick +=new EventHandler((timerSender,args) =>
{
autoCloseTimer.Stop();
ShowInfo(false);
});
autoCloseTimer.Start();
}
Whats meant to happen is that the method ShowInfo() opens up a box with the company info in and the dispatch timer auto closes it after said timespan. And this all works...
But what I'm not sure about is because the dispatch timer is a local var, after the Logo_MouseLeftButtonUp method finishes, what is there to keep the dispatch timer referenced and not availible for GC collection before the anonymous method is fired?
Is it the reference to the ShowInfo() method in the anonymous method?
Just feels like some thing I should understand deeper as I can imagine with using events etc it can be very easy to create a leak with something like this.
Hope this all makes sense!
Andy.
The DispatcherTimer registers itself with the Dispatcher by calling the internal Dispatcher.AddTimer method when you call Start.
Since it also unregisters itself by calling Dispatcher.RemoveTimer when you call Stop, you won't leak memory.
The Timer keeps the anonymous method alive in its Tick event, which also keeps the variables in the method alive through the closure.
One of the more obscure causes of memory leaks in .NET is event handlers. An event handler is a reference to an object, and keeps the object in scope. When you're done with an event handler, it needs to be dropped. If the event handler is used only once, it can deregister itself, but if it gets used more than once, there will need to be some other object that knows when it's no longer useful, and drops the event handler.