【问题标题】:What happens when timer threads don't finish on time当计时器线程未按时完成时会发生什么
【发布时间】:2017-01-26 10:35:27
【问题描述】:

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

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

如果我有一个函数需要大约 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% 之间波动。当然,在这一点上,它们的开始应该比结束要快得多。

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

【问题讨论】:

    标签: c# multithreading timer


    【解决方案1】:

    System.Windows.Forms.Timer 不同,System.Threading.Timer 使用线程池,如果您的计时器处理程序的完成时间超过计时器间隔,则不会被阻塞。

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

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

    这一切都由Timer 类和关联的线程池处理。

    MSDN 有这样的说法:

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

    因此,鉴于这段代码,其中计时器间隔为 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);
        }
    }
    

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

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

    【讨论】:

      【解决方案2】:

      我认为在 1 秒的计时器周期内会发生以下情况:

      • 在 0 秒:线程 1 启动。一个处理器正忙 -> ~13%
      • 在 1 秒时:线程 2 已启动。两个处理器忙 -> ~25%
      • 在 1.7 秒时:线程 1 完成。只有一个处理器忙 -> ~13%
      • 在 2 秒时:线程 3 启动。两个处理器忙 ->~25%
      • 在 2.7 秒时:线程 2 完成。只有一个处理器忙 -> ~13%
      • ...

      即线程的处理速度仍然比创建它们的速度快。即使是 500 毫秒也是如此。

      我认为,当您将计时器周期减少到

      【讨论】:

      • "我认为当您将计时器周期减少到
      猜你喜欢
      • 2015-01-29
      • 1970-01-01
      • 2010-10-14
      • 2017-02-14
      • 2013-06-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多