简体   繁体   English

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

[英]How to stop a System.Threading.Timer and cancel any callback that is running?

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. 特别是,如果正在运行回调,则会得到与互斥锁有关的ObjectDisposedException。
For the way the execution is structured, if I use that mutex on "Dispose" method, this causes a deadlock. 对于执行的结构方式,如果我在“ Dispose”方法上使用该互斥锁,则会导致死锁。
I have already thought of a solution: Use another try-catch block to handle exceptions related to the mutex. 我已经想到了一种解决方案:使用另一个try-catch块来处理与互斥锁有关的异常。

But I want to know if there is a method to force to cancel any callback of the timer when it is disposed. 但是我想知道是否有一种方法可以强制取消在处理计时器时的任何回调。

According to the documentation, you should use the Dispose(WaitHandle) overload: 根据文档,您应该使用Dispose(WaitHandle)重载:

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 the notifyObject parameter.Use this overload of the Dispose method if you want to be able to block until you are certain that the timer has been disposed. 该方法完成后,将WaitHandle notifyObject参数指定的WaitHandle如果希望能够阻塞直到确定计时器已被处置,请使用Dispose方法的此重载。 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: 如果您根本不想等待当前的回调执行,则可以遵循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;
    }

    ...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM