I have a problem replicated all over the application, but I think it could be managed the same way.
I have an IDisposable class in my Winforms application (it is a custom control derived from System.Windows.Forms.Label)
In that class, I have a timer whose tick event is this:
private void TickTimer(object state)
{
Action updateText = () =>
{
this.Parent.SuspendLayout();
this.Text = DateTime.Now.ToString("HH:mm:ss");
this.Parent.ResumeLayout(false);
};
if (this.InvokeRequired)
this.Invoke(updateText);
else
updateText();
}
On the other hand, this is the Dispose method:
protected override void Dispose(bool disposing)
{
if (disposing)
{
Stop();
_timer.Dispose();
}
base.Dispose(disposing);
}
The problem is when closing the application, an exception is thrown in this.Invoke(updateText) call, telling that the main form (where the control is placed) has been disposed.
Since this occurs assynchronously, How can I manage this?
I have thought about placing a class field called, for example, _isDisposed and in every line of TickTimer, to check if it was disposed, but this is really ugly.
By searching here in StackOverflow, I have found some advices.... none worked. Final attempt was using an "updating" flag.
private void TickTimer(object state)
{
_updating = true;
Action updateText = () =>
{
this.Parent.SuspendLayout();
this.Text = DateTime.Now.ToString("HH:mm:ss");
this.Parent.ResumeLayout(false);
_updating = false;
};
if (this.InvokeRequired)
this.Invoke(updateText);
else
updateText();
}
and in Dispose method:
protected override void Dispose(bool disposing)
{
if (disposing)
{
Stop();
_timer.Dispose();
while (_updating) ;
}
base.Dispose(disposing);
}
But the same error occurs. It seems that the parent form is disposed before the child controls.
What is the best way to do it?
Jaime