Reputation:
Example of my code:
Timer timer = new Timer(Timer_Tick, null, Timeout.Infinite, Timeout.Infinite);
Mutex timerSync = new Mutex();
void StartWork()
{
timer.Change(0, 1); //Start timer
//Do something...
}
void Dispose()
{
timer.Change(Timeout.Infinite, Timeout.Infinite); //Stop timer
timer.Dispose();
timerSync.Dispose();
//Dispose other things...
}
void Timer_Tick()
{
if (timerSync.WaitOne(0))
{
try
{
//Do something...
}
catch (Exception)
{
//If any exception occurs, abort the "Tick" callback!
return;
}
finally
{
//Whatever happens, release the mutex!
timerSync.ReleaseMutex();
}
}
}
When I stop the timer and dispose it, this not stops the current callback, that generates errors.
In particular, if a callback is in running, I get an ObjectDisposedException related to the mutex.
For the way the execution is structured, if I use that mutex on "Dispose" method, this causes a deadlock.
I have already thought of a solution: Use another try-catch block to handle exceptions related to the mutex.
But I want to know if there is a method to force to cancel any callback of the timer when it is disposed.
Upvotes: 0
Views: 1999
Reputation: 32058
According to the documentation, you should use the Dispose(WaitHandle)
overload:
Releases all resources used by the current instance of Timer and signals when the timer has been disposed of.
When this method completes, it signals the
WaitHandle
specified by thenotifyObject
parameter.Use this overload of theDispose
method if you want to be able to block until you are certain that the timer has been disposed. The timer is not disposed until all currently queued callbacks have completed.
void Dispose()
{
timer.Change(Timeout.Infinite, Timeout.Infinite); //Stop timer
var waiter = new ManualResetEvent(false);
timer.Dispose(waiter);
waiter.WaitOne();
waiter.Dispose();
timerSync.Dispose();
//Dispose other things...
}
If you don't want to wait for the current callback to be executed at all, you could follow the IDisposable
pattern:
Timer timer = new Timer(Timer_Tick, null, Timeout.Infinite, Timeout.Infinite);
Mutex timerSync = new Mutex();
private bool _disposed;
void Dispose()
{
_disposed = true;
...
}
void Timer_Tick()
{
if (_disposed)
{
return;
}
...
}
Upvotes: 2