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

标签 c# multithreading timer

我正在使用 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% 之间波动。

将周期更改为 500ms,CPU 使用率随后在 38% 和 50% 之间波动。当然,此时他们的开始速度应该比结束速度快得多。

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

最佳答案

System.Windows.Forms.Timer 不同,System.Threading.Timer 使用线程池,并且在以下情况下不会被阻塞您的计时器处理程序需要比计时器间隔更长的时间才能完成。

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

How are these threads managed? What is limiting the amount created when the polling rate is faster than the rate at which threads can be finished?

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

MSDN 是这样说的:

The callback method executed by the timer should be reentrant, because it is called on ThreadPool threads. The callback can be executed simultaneously on two thread pool threads if the timer interval is less than the time required to execute the callback, or if all thread pool threads are in use and the callback is queued multiple times. 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);
    }
}

enter image description here

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

enter image description here

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

enter image description here

关于c# - 当计时器线程没有按时完成时会发生什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41871547/

相关文章:

c++ - 不能像 store 一样在 x86 上放宽原子 fetch_add 重新排序,稍后加载?

python - PyQt5。从单独的线程控制 GUI

java - 图像大小造成计时器问题

c# - DateTime.TryParseExact 为 MM/dd/yyyy hh 返回 false :mm

c# - 在多个页面上打印流程文档滚动查看器

c# - Ninject.ActivationException : Error activating IMainLicense 错误

c# - 自动调整面板上呈现的多个表单的大小

java - 尽管保护写操作仍获取竞争条件 - Java

timer - 如何停止 ATmega328 上的定时器

asp.net - 如何防止asp :Timer from sending tick before response is generated?