如何停止System.Threading.Timer并取消正在运行的任何回调



我的代码示例:

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();
}
}
}

当我停止计时器并处理它时,这不会停止当前的回调,因为它会产生错误
特别是,如果回调正在运行,我会得到一个与互斥对象相关的ObjectDisposedException
就执行的结构而言,如果我在"Dispose"方法上使用互斥锁,就会导致死锁
我已经想到了一个解决方案:使用另一个try-catch块来处理与互斥体相关的异常。

但我想知道是否有一种方法可以在定时器被释放时强制取消它的任何回调。

根据文档,您应该使用Dispose(WaitHandle)重载:

释放计时器当前实例使用的所有资源,并在计时器已被释放时发出信号。

当此方法完成时,它会向notifyObject参数指定的WaitHandle发出信号。如果您希望能够阻止,请使用Dispose方法的此重载,直到您确定计时器已被释放。在完成所有当前排队的回调之前,不会释放计时器。

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...
}

如果您根本不想等待当前回调的执行,您可以遵循IDisposable模式:

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;
}
...
}

最新更新