首页 文章

当计时器线程没有按时完成时会发生什么

提问于
浏览
4

我正在使用System.Threading计时器来轮询不同线程上的传感器(由于通信延迟,一次一个很慢) . 它还允许用户通过更改计时器周期来更改轮询速率 .

如果计时器在下一个时期之前没有完成,那么我无法解决的问题是什么 . 我写了一个测试程序,但它没有真正回答任何问题 .

如果我有一个运行大约需要1.7秒并且每10秒调用一次的函数,它会在下一个启动之前完成,并且我的CPU使用率在13%(一个核心100%)和0%之间波动 .

t = new Timer(doWork, null, 0, 10000);

private void doWork(object o)
{
    for(int i = 0; i < numberItts; i++)
    {
    }
}

如果我然后将计时器周期降低到1秒,我会期望它在前一个完成之前不执行线程,或者继续生成新线程,并且随着更多线程在其他完成之前启动,CPU使用率将会上升 . 实际发生的是CPU使用率在13%到25%之间波动 .

将周期更改为500毫秒,CPU使用率将在38%和50%之间波动 . 当然,在这一点上,他们应该比他们结束时更快地开始 .

这些线程是如何管理的?当轮询速率快于完成线程的速率时,限制创建的数量是多少?

2 回答

  • 2

    System.Windows.Forms.Timer 不同, System.Threading.Timer 使用 thread pool ,如果您的计时器处理程序花费的时间超过计时器间隔,则不会被阻止 .

    因此,如果您的 doWork 完成"~1.7s"并且您的计时器间隔为1秒,您可能会看到多个并发线程进入 doWork .

    这些线程是如何管理的?当轮询速率快于完成线程的速率时,限制创建的数量是多少?

    这全部由 Timer 类和相关的线程池处理 .

    MSDN有这样的说法:

    计时器执行的回调方法应该是可重入的,因为它是在ThreadPool线程上调用的 . 如果定时器间隔小于执行回调所需的时间,或者所有线程池线程都在使用且回调多次排队,则可以在两个线程池线程上同时执行回调 . 更多...

    因此,给定这段代码,其中定时器间隔为2秒,处理程序处理时间为1秒,我们可以期望每次都使用相同的线程,因为通常更好地重用相同的线程而不是重新启动新线程:

    class Program
    {
        static void Main(string[] args)
        {
            var t = new Timer(doWork, null, 0, 1000);
    
    
            Console.WriteLine("Press any key to quit");
            Console.ReadKey();
        }
    
        private static void doWork(object o)
        {
            Console.WriteLine("Thread: {0}", Environment.CurrentManagedThreadId);
    
            // simulate lengthy process
            Thread.Sleep(1000);
        }
    }
    

    enter image description here

    将间隔和处理时间更改为1秒,由于轻微重叠导致随机线程 .

    enter image description here

    将间隔更改为200毫秒并将处理时间保持为1秒会导致工作线程数量比以前更多 . 原因是线程池已经意识到委托的完成时间比定时器间隔要长,所以它试图跟上:

    enter image description here

  • 7

    我认为以下1s的计时器周期发生以下情况:

    • 在0秒:启动线程1 . 一个处理器忙 - > ~13%

    • at 1秒:启动线程2 . 两个处理器忙 - > ~25%

    • 在1.7秒:线程1完成 . 只有一个处理器忙 - > ~13%

    • 在2秒时:启动线程3 . 两个处理器忙 - > ~25%

    • 在2.7秒:线程2完成 . 只有一个处理器忙 - > ~13%

    • ......

    即仍然会比处理线程更快地处理线程 . 即使是500毫秒也是如此 .

    我认为当你将定时器周期减少到一个<1.7s / 8 = ~0.2125s的值时,你会发生预期的行为(假设有8个处理器可用,除了处理你的线程需要1.7s之外什么都不做 . )

相关问题