在退出程序之前等待System.Threading.Timer回调完成

Eri*_* J. 11 c# multithreading timer

我有一个List<System.Threading.Timer>.每个Timer以可配置的间隔(默认为10分钟)触发.All调用相同的回调方法(使用不同的参数).回调方法可能需要几秒钟才能完成它的工作.

当程序终止时,看起来回调方法的执行会立即停止(我是否正确看到了?).

在退出程序之前,如何优雅地等待任何当前正在执行的回调方法?

Tom*_*mek 17

您可以使用WaitHandler参数处理所有计时器.只有当回调方法完成时才会发出此处理程序的信号(如规范所述:"在所有当前排队的回调都完成之前,不会释放计时器.")

void WaitUntilCompleted(List<Timer> myTimers)
{
    List<WaitHandle> waitHnd = new List<WaitHandle>();
    foreach (var timer in myTimers)
    {
        WaitHandle h = new AutoResetEvent(false);
        if(!timer.Dispose(h)) throw new Exception("Timer already disposed.");
        waitHnd.Add(h);
    }
    WaitHandle.WaitAll(waitHnd.ToArray());
}
Run Code Online (Sandbox Code Playgroud)

编辑:@Peter强调了Dispose方法返回值的重要性.当计时器已经处理时,它返回false.为了确保这个解决方案保持可靠,我修改它以在Timer已经处理时抛出异常,因为在回调完成时我们无法控制这种情况,尽管早期的处理回调可能仍在运行!


Pet*_*aki 6

Tomek 接受的答案很好,但不完整。如果 Dispose 函数返回 false,则意味着不需要等待完成,因为线程已经完成。如果您在这种情况下尝试等待 WaitHandle,WaitAll 将永远不会返回,因此您创建了一个任意冻结应用程序/线程的函数。

这是它的外观:

    void WaitUntilCompleted(List<Timer> myTimers)
    {
        List<WaitHandle> waitHnd = new List<WaitHandle>();
        foreach (var timer in myTimers)
        {
            WaitHandle h = new AutoResetEvent(false);
            if (timer.Dispose(h))
            {
                waitHnd.Add(h);
            }
        }
        WaitHandle.WaitAll(waitHnd.ToArray());
    }
Run Code Online (Sandbox Code Playgroud)