定时器随机不触发

本文关键字:随机 定时器 | 更新日期: 2023-09-27 18:05:39

我有这样的代码

mTestModeMetadataTimer = new System.Threading.Timer(SomeTimerCallback, null, 1000, Timeout.Infinite);
Stopwatch tmStopwatch = new Stopwatch();
private void SomeTimerCallback(object state)
{
    // doing minimal work here
    Console.WriteLine("{0}: SomeTimerCallback time: {1}", System.Threading.Thread.CurrentThread.ManagedThreadId, tmStopwatch.ElapsedMilliseconds);
    tmStopwatch.Restart();
    // Better to be on the safe side and do this slightly more than once per second, than slightly less.
    mTestModeMetadataTimer.Change(990, Timeout.Infinite);
}

一切正常,除了定时器事件之间偶尔会有巨大的延迟,如以下控制台输出所示。

 31: SomeTimerCallback time: 998
 21: SomeTimerCallback time: 997
 20: SomeTimerCallback time: 999
 3: SomeTimerCallback time: 989
 3: SomeTimerCallback time: 1000
 3: SomeTimerCallback time: 994
 37: SomeTimerCallback time: 999
 3: SomeTimerCallback time: 991
 29: SomeTimerCallback time: 1002
 37: SomeTimerCallback time: 1000
 3: SomeTimerCallback time: 17568
 3: SomeTimerCallback time: 999
 29: SomeTimerCallback time: 993

这只是相当大的应用程序的一小部分。同样的行为也存在于System.Timers.Timer中,事实上,在整个应用程序的其他时间也会发生。我将线程ID添加到这个特定计时器的控制台输出中,希望能更深入地了解为什么在正确的1秒事件中有一个随机的17.5秒的运行时间。

有什么我明显做错了吗?也许我可以收集更多的数据来弄清楚为什么我的计时器表现得很奇怪?

定时器随机不触发

从您的评论来看,发生这种情况的原因是您正在耗尽线程池中的线程。因为每个线程都在使用,所以计时器必须等待17.5秒才能让一个线程可用。

你的选择,因为我看到它要么增加线程池中的最大线程数,要么使用不使用线程池的不同定时器( System.Timers.Timer与不使用线程池的同步对象(仍然使用线程池来启动它)或System.Windows.Forms.Timer与消息泵运行)

System.Threading.Timer调用从CLR线程池中获得的工作线程的事件处理程序。如果线程池处于饥饿状态,则可能会发生回调队列,直到线程被释放。

要检查是否耗尽了线程池,可以在调试时定期记录可用线程的数量:

int workerThreads;
int completitionPortThreads;
System.Threading.ThreadPool.GetAvailableThreads(out workerThreads, out completitionPortThreads);

尝试在Timer构造函数中使用periodic:

mTestModeMetadataTimer = new System.Threading.Timer(SomeTimerCallback, null, 1000, TimeSpan.FromMilliseconds(990));

你确定你没有进入调试模式,并且在继续之前让时间过去了吗?