【问题标题】:How to stop a System.Threading.Timer and cancel any callback that is running?如何停止 System.Threading.Timer 并取消正在运行的任何回调?
【发布时间】:2018-07-30 01:58:13
【问题描述】:

我的代码示例:

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 块来处理与互斥锁相关的异常。

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

【问题讨论】:

标签: c# multithreading timer mutex


【解决方案1】:

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

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

当此方法完成时,它会向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;
    }

    ...
}

【讨论】:

  • 对于第二个示例,您需要锁定 Disposing 位和 Tick,或者您可以同时在两者中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-04
  • 1970-01-01
  • 2018-08-18
  • 1970-01-01
  • 1970-01-01
  • 2021-09-10
相关资源
最近更新 更多