Do I need to unsubscribe from a GestureRecogniser in Xamarin.Forms? - c#

So I have the following Control, extended from Label
public Hyperlink()
{
var tapGesture = new TapGestureRecognizer();
tapGesture.Tapped += TapGesture_Tapped;
this.GestureRecognizers.Add(tapGesture);
}
Now my question is, do I need to unhook the GestureRecogniser?
My understanding of GarbageCollection is that because the Hyperlink object is in charge of the tapGesture it should be able to dispose of it; but this is the world of Xamarin.Forms where anything goes.
So do I need the Dispose code to avoid a potential memory leak and avoid keeping the object alive
public void Dispose()
{
if (this.GestureRecognizers.Count > 0)
{
var tapGesture = this.GestureRecognizers[0] as TapGestureRecognizer;
tapGesture.Tapped -= TapGesture_Tapped;
this.GestureRecognizers.Clear();
}
}
This link, as well as this link say that I should be removing GestureRecognisers but does not expand on why

According to Cross-Platform Performance, suggest you unsubscribe from GestureRecogniser.
To prevent memory leaks, events should be unsubscribed from before the subscriber object is disposed of. Until the event is unsubscribed from, the delegate for 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 this reference, garbage collection will not reclaim the subscriber object memory.

Unless you use persistent pages, you do not need to manually dispose of your gesture recognizer. it will be destroyed when whatever page was using it is popped and collected by GC.
If it puts you at ease, you can still manually dispose of it and it won't hurt anything, but it is not required.

Related

Can event listener of WeakEvent be deleted by garbage collection any time?

I'm looking for a solution avoiding memory leaks when using events (which may occur if the listener is never removed from the event source. I found this code project article describing a WeakEvent class like this:
sealed class EventWrapper
{
SourceObject eventSource;
WeakReference wr;
public EventWrapper(SourceObject eventSource,
ListenerObject obj) {
this.eventSource = eventSource;
this.wr = new WeakReference(obj);
eventSource.Event += OnEvent;
}
void OnEvent(object sender, EventArgs e)
{
ListenerObject obj = (ListenerObject)wr.Target;
if (obj != null)
obj.OnEvent(sender, e);
else
Deregister();
}
public void Deregister()
{
eventSource.Event -= OnEvent;
}
}
As far a I understood the listener object is wrapped in a WeakReference, which is not considered as a reference to the event listener from the Garbage Collectors' point of view.
My question: When using this pattern, is it possible that the Garbage Collector deletes ListenerObject obj though no event was fired by the event source beforehand? In that case, the whole pattern becomes indeterministic since the fired event is not forwarded to the ListenerObject, because the Garbage Collector deleted it (because there is only a WeakReference pointing to it). If this is correct why should I use a pattern like this anyway?
Thx
Yes, if the WeakReference is the only thing which holds a reference to ListenerObject, then ListenerObject can be GC'd at any point.
You would use a pattern like this if your EventWrapper class is not the only thing which has a reference to ListenerObject, but your EventWrapper doesn't know when that other thing is going to release its reference to ListenerObject.
For example, ListenerObject might be a UI control which appears on a screen, and the EventWrapper might be owned by a singleton service. The UI control will stay alive as long as that screen is shown, but will be released when the user changes the screen. The service might not know when that happens. Using a weak event pattern means that you don't accidentally end up with a memory leak in this case.
Note, if you do want to implement the weak event pattern, use a WeakEventManager as detailed in this article.

C# Dispose(), unsubscribe from events

Is this the right away to call dispose and unsubscribe from events in this context? context_ is used to manage a simple statemachine that we start and stop essentially by creating a new one.
class ClassA
{
StateContext context_;
void SomeMethod()
{
if(context_ != null)
context_.Dispose();
context_ = new StateContext();
}
class StateContext : IDisposable
{
SubClassA()
{
//Subscribe to an event
}
void Dispose()
{
//unsubscribe to an Event
}
}
}
A well-behaved object should not require cleanup beyond calling Dispose. If an object subscribes to events from other objects that may outlive it, it must (to be well-behaved) ensure that those events get cleaned up somehow. This may be done either be using weak events, or by having Dispose take care of the event subscriptions.
Note that the term "unmanaged resource" has only minimal relation to the term "unmanaged code", and that normal events from long-lived objects are unmanaged resources. As such, even though events have nothing to do with unmanaged code, it is entirely right and proper to use IDisposable to clean them up. Indeed, I would suggest that such cleanup should be considered obligatory unless some other means exists to ensure cleanup (e.g. events are handled with a weak-event manager, or the object whose event is subscribed won't outlive the subscriber). WinForms code is often sloppy, on the presumption that event publishers won't outlive subscribers, but that doesn't mean such sloppiness should be considered desirable.

Do I have to remove eventHandlers in a finalizer?

I have a model class that has a Saved event. The idea is that if two viewmodels use that model object, if one of them changes it, the other will be updated.
Do I have to remove the event handler when I am no longer using its view model? Here is my code:
protected AbstractEntityViewModel(AbstractEntity ae)
{
this.ae = ae;
ae.Saved += delegate(object o, EventArgs e)
{
base.OnPropertyChanged(null);
};
}
Is this ok, or do I need to change this so that I can -= get rid of the delegate when the viewmodel is no longer used?
Direction of event References
To know whether you really need to detach the event handler, you've first got to understand that:
ae.Saved += delegate(object o, EventArgs e)
{
base.OnPropertyChanged(null);
};
means ae is now referencing this. So the object with the event is referencing the object with the event handler. It's not the other way around (event handler referencing event).
Objects not referenced by GC root can be collected
Furthermore, while ideally objects to be garbage collected are not referenced by any other objects, that is not strictly necessary:
The garbage collector can collect all objects which are not referenced by a GC root in any way (path). This means if you've got an insular graph of objects (objects referencing other objects of the graph, but there is no object outside the graph which is referencing an object inside the graph [no GC root either]), then the entire object graph will eventually be garbage collected. The more intertwined the graph is, the more expensive it is for the GC to collect it. Detaching event handlers helps in dissolving such graphs more speedily.
Correctly cleaning up objects
.Net does not feature Destructors. Instead there is the IDisposable pattern and finalizers (see Implementing Finalize and Dispose to Clean Up Unmanaged Resources).
Long story short:
Finalization methods (~Foo () { } for class Foo) are needed when an object manages unmanaged resources. They are called by the garbage collector when the GC is collecting the object. So the exact moment is not up to you.
Disposable pattern can be used to clean-up managed as well as unmanaged resources. If the object has got unmanaged resources, it must still have a finalizer. Why? The Dispose() method is called by you. There is no guarantee that it's being executed. If the application fails to call the Dispose() method, there's still the GC which calls finalize. So basically doing unmanaged-resource cleanup in Dispose is just a performance improvement (which, under some circumstances, may be very important, unless you want to plug in a few more gigabytes of RAM into the computer...).
If you plan to use a finalizer i absolutely urge you to read the docs on it, because there's quite a few things which i didn't cover here. See Implementing Finalize and Dispose to Clean Up Unmanaged Resources
Your example
To come back to your example, after you construct a AbstractEntityViewModel, it will stay alive as long as the AbstractEntity you've passed to the AbstractEntityViewModel stays alive and vice versa.
But when neither of those two are referenced by a GC root, both of them are garbage collected.
If you detach the event handler, the AbstractEntityViewModel (or rather it's concrete sub-class instance) can be garbage collected even if the AbstractEntity can't.
Also see: Understanding Garbage Collection in .NET
Long and short of it is yes. The secondary object can not be disposed of if the AbstractEntity object still has a reference to it. IF there is a chance that the object will be disposed and the Event is still around (this holds true for static events too) then you need to manually remove the eventhandler or the object will not be disposed.
Events can be though of as being a primitive observer implementation: The subject retains a handler to every subscribed observer, meaning they are unable to be garbage collected. To allow the observer to be garbage collected, it must be removed as an observer from the subject.
The only time where event handlers do not need to be manually removed are when the subject and the observer are the same instance, as the garbage collector will detect the circular reference and subsequently finalize the object.

Adding and Removing Event Handler in .net

i recently created a sample application, wherein i implemented the events and delegates, when the Properties value is changed this event will raise, i have a question regarding events
Does event objects are created in memory? or they are just static object which gets removed once the event is fired?
Is it necessary to remove the handler once the event is executed, to free-up resources. does removing handler once done, boost's up the application performance, i am talking about the application which are using lots of events
Events do take memory and are not garbage collected until after you unsubscribe from them. They are a common cause of memory leaks.
Events can be both static and instance bound. Subscribers to the event are never removed while the event broadcaster is alive, unless implicitly done so, usually with the -= operator.
Yes, yes and yes. If you don't clean-up your subscribers you have a memory-leak waiting to happen.
If all this is a concern to you perhaps you could look into the WeakEvent pattern.
events are like delegates ( with another layer of protection) .
when you register to an event - you are actually making a reference to another object.
this object can't go through GC because you made a reference to it !
it isnt "un-referenced".
but your object CAN go through GC. ( if un-referenced).
so you end up with memory leak.
you should manually remove the reference .

unsubscribing events from class?

I need bit of advise on best practice for this type of scenario. I searched but dont find any satisfying answer.
We use a 3rd party (.net) DLL in our winforms project. It raises some events and we subscribe to. Question is , do i need to explicitly unsubscribe these events in my class ?
BTW we both use .net framework 4. Thanks for the advise.
some sample code ...
public class MyClientCode: IDisposable
{
private readonly 3rdParty.TheirClass _theirClass;
public MyClientCode()
{
_theirClass = new _theirClass()
_theirClass.ReadData += ReadDataEvent;
}
public void SomeOtherMethod()
{
//some other code
}
public void ReadDataEvent()
{
//some code
}
public void Dispose()
{
_theirClass.ReadData -= ReadDataEvent;
}
}
and in the button click event, i do ...
MyClientCode code = new MyClientCode();
code.SomeOtherMethod();
If you don't unsubscribe, the object that subscribed to the event will not be garbage collected (it will be kept in memory). This can create memory leaks and lead to excessive memory usage.
However, if the event has a shorter or same lifetime as the class that contains it, in your case, the memory will be collected properly. If you have another object reference a non-private event, then you will run into issues.
See MSDN:
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.
Note that you don't need to unsubscribe if you are exiting your application, only in cases where it shouldn't be held in memory. (For example, when you close a window in your application, you should unsubscribe from any events, or else the window will still be held in memory.) If the containing object is destroyed manually, the events will also be destroyed.

Categories

Resources