|
-
September 16th, 2008, 08:24 AM
#1
Safe Handling of Timers
I need to know if there is a safe way to handle timers in a Component.
Specifically, I need to ensure the timer is stopped and destroyed.
If I have a User Control:
Code:
class MyControl : UserControl
{
private Timer timer = new Timer();
public MyControl()
{
...
timer.Start();
...
}
}
Now suppose that user control is placed into a form. I need to ensure that the timer gets stopped if the form containing the control is closed. How can I do that?
Eggman
Using: VS 2008 w. Net 3.5
-
September 16th, 2008, 01:38 PM
#2
Re: Safe Handling of Timers
Handle the Form's OnClosed event.
-
September 17th, 2008, 08:44 AM
#3
Re: Safe Handling of Timers
 Originally Posted by Arjay
Handle the Form's OnClosed event.
The problem is that the timer is part of a User Control not a Form, so in the context where the timer exists, it doesn't know about the form.
Unless I can do something like:
this.ParentForm
Eggman
Using: VS 2008 w. Net 3.5
-
September 17th, 2008, 09:23 AM
#4
Re: Safe Handling of Timers
Okay, so using:
Code:
this.ParentForm.FormClosing += StopTimer;
I am able to ensure the timer gets stopped. However, the issue now is that in order to attach this callback, I had to do a hack with a "runonce" variable in the timer loop. The problem is that everywhere I have tried to attach the StopTimer callback, the ParentForm is null because the control has not yet been attached to a form.
What I need now is a way to know when the ParentForm is no longer null so that I can start the timer at that point and attach the callback.
Eggman
Using: VS 2008 w. Net 3.5
-
September 17th, 2008, 11:48 AM
#5
Re: Safe Handling of Timers
Can't you create a StopTimer method in your user control and call that method from your form closing event?
Code:
private void MyParentForm_FormClosing( object sender, FormClosingEventArgs e )
{
myUserControl.StopTimer( );
}
Better yet, can you override the control's Dispose method and do it in there?
Code:
private void MyParentForm_FormClosing( object sender, FormClosingEventArgs e )
{
myUserControl.Dispose;
}
-
September 18th, 2008, 10:19 AM
#6
Re: Safe Handling of Timers
 Originally Posted by Eggman002
...What I need now is a way to know when the ParentForm is no longer null so that I can start the timer at that point and attach the callback.
Don't know if that's the best way to do it, but just override the ParentForm property, check for null in the setter, and attach the handler there.
I think the Dispose method is cleaner, though.
-
September 28th, 2008, 12:37 PM
#7
Re: Safe Handling of Timers
Doing it on Dispose is fine, so long as I can ensure that the control is disposed. Simply closing the form does not seem to necessarily call the dispose method.
I could call dispose from the parent OnFormClosing event, but of course I still run into the problem of ensuring the Parent is not null.
Eggman
Using: VS 2008 w. Net 3.5
-
September 28th, 2008, 02:14 PM
#8
Re: Safe Handling of Timers
Dispose gets called when the GC kicks in, not when the form closes.
You can ensure that Parent isn't null by creating your own constructor which requires the parent form to be passed in.
-
September 28th, 2008, 02:50 PM
#9
Re: Safe Handling of Timers
You can ensure that Parent isn't null by creating your own constructor which requires the parent form to be passed in.
If you do this and don't supply a default constructor then your user control won't work in the designer any more.
You have to handle the parent changed events of all parents of the control until a parent is added which is a Form.
Have a look at this code :
Code:
public class ParentFormClosingHandler
{
private Control _baseControl;
private Form _form;
public event FormClosingEventHandler Closing;
public ParentFormClosingHandler(Control control)
{
ProcessControl(control);
}
void _baseControl_ParentChanged(object sender, EventArgs e)
{
_baseControl.ParentChanged -= new EventHandler(_baseControl_ParentChanged);
ProcessControl(_baseControl);
}
void _form_FormClosing(object sender, FormClosingEventArgs e)
{
if (sender == _form)
{
OnFormClosing(e);
}
}
protected virtual void OnFormClosing(FormClosingEventArgs e)
{
if (Closing != null)
{
Closing(_form, e);
}
}
private void ProcessControl(Control control)
{
while (control.Parent != null)
{
control = control.Parent;
}
_form = control as Form;
if (_form == null)
{
_baseControl = control;
_baseControl.ParentChanged += new EventHandler(_baseControl_ParentChanged);
}
else
{
_form.FormClosing += new FormClosingEventHandler(_form_FormClosing);
}
}
}
You use it thus :
Code:
public class MyUserControl : UserControl
{
private ParentFormClosingHandler _formClosingHandler;
public MyUserControl()
{
InitializeComponent();
_formClosingHandler= new ParentFormClosingHandler(this);
_formClosingHandler.Closing += new FormClosingEventHandler(_formClosingHandler_Closing);
}
private void _formClosingHandler_Closing(object sender, FormClosingEventArgs e)
{
// ....
}
}
What happens is
(1) The ParentFormClosingHandler hooks into the user control's parent changed event.
(2) When this is fired, the control's parent is checked to see if it's a form.
(3) If not then the control's parent's parent changed event is handled (an so on and so on until...)
(4) If the parent is a form then this form's closing event is handled.
Get the idea ?
Darwen.
Last edited by darwen; September 28th, 2008 at 03:06 PM.
-
September 28th, 2008, 05:46 PM
#10
Re: Safe Handling of Timers
 Originally Posted by Arjay
Dispose gets called when the GC kicks in, not when the form closes
Not true. The GC never calls dispose on any class. The GC will always call a destructor though. If a destructor has been defined in a class, it is guaranteed to be called (at some stage) before the object is garbage collected. You can make the destructor call the Dispose method if you want, which is what is generally done to ensure that unmanaged resources are always released.
Ideally though, you'd call Dispose before losing the last reference to the object as you could be waiting minutes/hours/days for the destructor to be called.
Last edited by Mutant_Fruit; September 28th, 2008 at 05:55 PM.
www.monotorrent.com For all your .NET bittorrent needs
NOTE: My code snippets are just snippets. They demonstrate an idea which can be adapted by you to solve your problem. They are not 100% complete and fully functional solutions equipped with error handling.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|