WinForms and event handlers - c#

By default when you create a Win-Form a application, This is the code generated by visual studio to dispose the Form.
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
Is this enough?Or I should unregister all events so the controls will be ready to collected by the garbage collector?
if (disposing && (components != null))
{
myButton.OnClick-= MyFunction; //may be here!!
// ... all events used
components.Dispose();
}

The form must unregister all events from entities which will outlive the form. It doesn't matter if the form unregisters events from entities which have the same lifetime as the form. For whatever reason, the normal doctrine seems to be "don't worry about unregistering events, except when it matters". I would think it would be much cleaner to have all objects which subscribe to events unsubscribe them on Dispose, but unfortunately neither vb.net nor C# provides any even-remotely-clean way to accomplish this. With dependencies that implement IDisposable, it's possible to wrap construction in a routine which will add the newly-created item to a list of things to be cleaned up later. One can then perform all necessary cleanup by simply calling Dispose on everything in the list. Unfortunately, from the perspective of .net, there's no nice way to write a general-purpose routine which will simultaneously subscribe to an event and return an Action<>, IDisposable, or other such object which could be used to unsubscribe.

No, the garbage collector takes care of it. The event can never be raised anymore since the form instance was disposed which in turn disposed the button. There is a circular reference between the form and the button due to the event handler but the garbage collector has no trouble with them.

If this is the form that is a subject to often close and open operations, and use massive amount of events inside it, it's important to unregister all events. Cuase events consume resources definitely.
If this is a form that appears ones a while, or could even not appear ever, or it is, let's say, yuor application's MainForm, it's not important to unsubscribe from events.
What about a place where to do that, I would personally, unsubscribe inside, let's say inside Closing override and not in Dispose().

Related

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

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.

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.

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 .

Remove handler when usercontrol is disposing

Which one is the right one?
This one:
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
this.ctlRBContent1_GetBuildName -= _ctlBottom.GetBuildName;
components.Dispose();
}
base.Dispose(disposing);
}
OR
This one:
~ ctlRemoteBuildContent1()
{
this.ctlRBContent1_GetBuildName -= _ctlBottom.GetBuildName;
}
I tried to toggle this 2 functions. When I did UserControl disposing, it didn't jump into the toggle line :/
If you clean up in a destructor, there's no guarantee as to when the destructor will be run. Objects with a destructor also require more work for the garbage collector to handle. It's preferable therefore to implement IDisposable, which is your first example.
Note that your code snippet does not fully implement the recommended IDisposable pattern. Please see this article for a good and complete explanation:
http://www.csharphelp.com/2010/02/c-garbage-collecting-destructors-versus-dispose/
In your code snippet, if for some reason components is null, you would not remove the event handler. The null check for components should only be done to protect the components.Dispose() call.
protected override void Dispose(bool disposing)
{
if (disposing)
{
this.ctlRBContent1_GetBuildName -= _ctlBottom.GetBuildName;
if (components != null)
{
components.Dispose();
}
}
base.Dispose(disposing);
}
The second bit of code is called by the finalizer, which means you won't be able to tell when this is called (depends on when the garbage collector runs). Ideally you want to free your resources as soon as possible, typically in a Dispose(). So use the dispose pattern here.
Why do you want to unsubscribe that event here? What does it contain?
Which one is the right one?
A slightly obnoxious answer is "both" ;-) ...
Ideally you want the tidying up to happen in the Dispose method so it can be performed as soon as possible, but in some situations it's important to also have the tidy up code called from the destructor as a back-up in case an object gets used without being disposed (...I guess it depends on how likely you think this could be!?)
The dispose pattern (mentioned in the other answers) provides a way of implementing this without code duplication between the dispose and destructor, and with the GC.SupressFinalize makes sure the object's garbage collection doesn't get held up unnecessarily if the tidy up has been done.

Simply open and close dialog winform will increase memory usage

I am trying to reduce memory usage of a winForm application.
There is a main form and a setting form in the application. When "Setting" button been pressed, the setting form will popup as a modal form, the Setting form will load app.config data from config file and read them to memory as Hashtable. After the setting form closed, it will call Dispose method inherented from Windows.Forms.Form. The Dispose method is as simple as set the Hashtables and app.config object to null.
Show SettingForm as modalform:
private void btnSettings_Click(object sender, EventArgs e)
{
frmConfig form = new frmConfig();
form.StartPosition = FormStartPosition.CenterScreen;
//MessageBox.Show(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase));
form.ShowDialog(this);
form.Dispose();
}
Dispose method:
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
// Release managed resources
Logger.Verbose("Disposing SettingForm");
mySetting = null;
testFtp = null;
}
base.Dispose(disposing);
}
Note: mySetting is a instance of Class with all the app.config data been load into Hashtable, and testFtp is a custom object for ftp function. Should I implement Dispose method for this two class and using
mySetting.Dispose();
testFtp.Dispose();
instead of set them to null, as they are themself/deal with unmanaged resources?
But each time push the "Setting" button and close the setting form will increase private Byte for a few hundreds K. Memory leak? How could I get rid of it?
As you suggested near the end of your question, I would recommend implementing IDisposable on mySetting and testFtp. You should see better cleanup of resources once you have implemented the following:
protected override void Dispose(bool disposing) {
if (disposing && (components != null)) {
components.Dispose();
// Release managed resources
Logger.Verbose("Disposing SettingForm");
mySetting.Dispose();
testFtp.Dispose();
}
base.Dispose(disposing);
}
Small edit:
Based on Nayan's answer and the answer he links to: I'd highly recommend the implementation of IDisposable. Using Forms and deriving from the Forms class screams, "Check for the need to implement IDisposable." This does not mean that your code should be implementing it, just that you should really check to make sure you don't need it. Forms typically have a lot of events published and subscribed to. Forms are also notorious for becoming a catch-all resource bucket, IMO.
The memory may not be getting released because of some other piece of code too. Since you have not provided much details, I'll assume right now that everything else is optimal.
The objects that you are working with are collected by garbage collector (as you know it). But they may not be released from memory when you want it. .NET objects are better left to garbage collector.
As per why the memory may not be getting released, you have the answers here.
Setting object reference to null doesn't make much difference. On the other hand, I've personally recorded some times, objects coming back alive (and pushed to old generations) because you're using them while setting null to same. It's another form of interference with GC, but your choice.
You may not need to implement IDisposable, but if you are working with streams, OS handles, unmanaged resources, you should then.
Edit:
The memory usage may be high, but it's GC's responsibility to free it as long as you do not keep references alive. So, if you have taken every precaution, it still may seem that your application is consuming lot of memory. That is acceptable as freeing the unreferenced objects is garbage collector's responsibility.
Why do you think it's a leak? GC is not obliged to free memory instantly, under some circumstances it may never actually perform the collection and that would be okay.
If you really need these kilobytes freed immediately, you might force GC to perform the clean-up just after the disposals, but it's a costly operation in general and may affect overall performance.

Categories

Resources