【问题标题】:C# timer synchronized with Datetime.Now与 Datetime.Now 同步的 C# 计时器
【发布时间】:2010-06-09 21:05:01
【问题描述】:

在 C# 中如何创建一个与系统 DateTime 的刻度同步的计时器。每当 DateTime.Now 的秒数发生变化时,自定义计时器就会打勾

【问题讨论】:

  • 你需要每秒触发一次,还是在一定范围内秒变时触发?目的是什么?
  • 我想在 DateTime.Now.Second 更改时触发。如果我启动一个时间跨度为 1 秒的计时器,它不会在系统时间更改时准确触发。
  • 您可以通过繁忙的等待循环来执行此操作,但希望有更好的方法。
  • 即使你尝试回调函数之类的东西,它也不会在第二个滴答声中被准确地调用。尝试在比目标少 10 毫秒的时间内入睡,这应该可以将您的准确度提高到几毫秒内。提高优先级也可能有助于提高准确性。

标签: c#


【解决方案1】:

您会发现,如果您检查之前关于 SO 的一些问题,您将很难获得计时器的准确性。以下是之前问题的一小部分示例:

这里是another previous question,它可以为您提供一些帮助。

【讨论】:

    【解决方案2】:

    您想要的精度是多少?

    如果你说 1ms 足够精确(或 10 或 100),你总是可以做一个循环来比较当前时间和从上一次迭代中保存的时间,并在当前时间的秒值时启动一个线程值变化...

    【讨论】:

      【解决方案3】:

      您可以使用一些调度库,例如 Quartz.net,它提供了示例且易于使用: http://quartznet.sourceforge.net/

      【讨论】:

        【解决方案4】:

        此代码使用 System.Threading.Timer。它将查看调用触发器的毫秒偏移量。如果错误超出了可接受的范围,它将重新调整计时器,并通过平均每个滴答的错误来纠正间隔。

        class Program {
            const int MAX_ERROR_IN_MILLISECONDS = 20;
            const int ONE_SECOND = 1000;
            const int HALF_SECOND = ONE_SECOND / 2;
        
            private static System.Threading.Timer timer;
        
            static void Main(string[] args) {
        
                timer = new System.Threading.Timer(Tick);
        
                timer.Change(ONE_SECOND - DateTime.Now.Millisecond, ONE_SECOND);
                Console.ReadLine();
            }
        
            private static int ticksSynced = 0;
            private static int currInterval = ONE_SECOND;
            private static void Tick(object s) {
                var ms = DateTime.UtcNow.Millisecond;
                var diff = ms > HALF_SECOND ? ms - ONE_SECOND : ms;
                if (Math.Abs(diff) < MAX_ERROR_IN_MILLISECONDS) {
                    // still synced
                    ticksSynced++;
                } else {
                    // Calculate new interval
                    currInterval -= diff / ticksSynced;
                    timer.Change(ONE_SECOND - ms, currInterval);
                    Console.WriteLine("New interval: {0}; diff: {1}; ticks: {2}", currInterval, diff, ticksSynced);
                    ticksSynced = 0;
                }
                Console.WriteLine(ms);
            }
        }
        

        如您所见,您无法准确触发 Windows 中的第二次更改。你可以试着靠近。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-12-15
          • 2015-08-23
          相关资源
          最近更新 更多