【问题标题】:How to run a timer at the TOP of each second? (when millis = 000)如何在每秒的 TOP 运行计时器? (当毫秒 = 000 时)
【发布时间】:2011-09-28 05:39:15
【问题描述】:

在我的应用程序中,我使用了System.Threading.Timer 的数量并将此计时器设置为每 1 秒触发一次。我的应用程序每 1 秒执行一次线程,但毫秒的执行是不同的。

在我的应用程序中,我使用了 OPC 服务器和 OPC 组。一个线程从 OPC 服务器读取数据(例如一个变量更改它的值,我想每 1 秒将更改值的这一时刻记录到我的应用程序中) 然后另一个读取此数据的线程每隔 1 秒从第一个线程读取此数据,第二个线程用于将数据存储到 MYSQL 数据库中。 在这个过程中,当我从第一个线程读取数据时,我将获得旧数据值,例如,第二次在 10:28:01.530 读取数据,然后我将获得第二次 10:28:00.260 的信息。所以我想管理这些线程,第一个线程以 000 毫秒工作,第二个线程以 500 毫秒工作。使用第一个线程在 000 秒更新数据,第二个线程在 500 毫秒读取数据。

我的输出如下:

10:28:32.875 10:28:33.390 10:28:34.875 …… 10:28:39.530 10:28:40.875

但是,我想要以下结果:

10:28:32.000 10:28:33.000 10:28:34.000 …… 10:28:39.000 10:28:40.000

如何设置计时器,以便在“000 毫秒”处执行回调?

【问题讨论】:

  • 严格来说,这是不可能的。但是,您想要这样做一定是有原因的。你能扩展一下这个问题吗?
  • @ xixonia :查看我的编辑

标签: c# .net timer


【解决方案1】:

首先,这是不可能的。即使您将“事件”安排在提前几毫秒触发的时间,然后将当前时间的毫秒部分与循环中的零进行比较,您的代码的流控制也可能会在任何时候被取消给定的时刻。

您将不得不重新考虑您的设计,而不是依赖于事件何时触发,而是考虑补偿延迟毫秒的算法。

此外,Threading.Timer 不会对您有太多帮助,如果您定期使用自己的线程,您将有更好的机会:

  • 检查当前时间,看看距离下一整秒还有多少时间
  • Sleep() 减去“香料”因子的金额
  • 做你必须做的工作。

您将根据您获得的结果来计算您的“香料”因素 - 睡眠是提前还是落后于计划完成。

如果您要提供更多信息,说明您显然需要在 0 毫秒内发生事件,我可以帮助您摆脱这种要求。

HTH

【讨论】:

  • 这正是我的建议。但香料因子的大小他必须自己选择,因为它可能因机器、线程数等而异。
  • 是的 - 如果我要这样做,我会自动选择“香料” - 我会测量延迟并相应地调整它,以便下一次迭代总是更准确和准时.
【解决方案2】:

我会说这是不可能的。您必须了解为 cpu 切换上下文需要时间(如果其他进程正在运行,您必须等待 - cpu shelduler 正在工作)。每个 CPU 滴答都需要一些时间,因此不可能同步到 0 毫秒。也许通过为您的流程设置高优先级,您可以接近 0,但您永远不会实现它。

【讨论】:

  • 我认为即使是 8086 的滴答声也不到 1 毫秒。这不是处理器的错 - 这是操作系统。无论滴答声有多长,RTOS 肯定能够做到这一点。
【解决方案3】:

恕我直言,要真正让计时器精确地每 1 秒(毫秒)触发一次是不可能的 - 即使在核心汇编程序中,这在您的普通 Windows 机器上也是一项非常艰巨的任务。

【讨论】:

    【解决方案4】:

    我认为首先您需要做的是:为计时器设置正确的到期时间。我这样做: 到期时间 = 1000 - DateTime.Now.Milliseconds + X;其中 X - 为准确性服务,您需要通过测试选择它。然后 Threading.Timer 每次它都会在 CLR 线程池的线程上运行,以及测试如何显示 - 这个线程每次都不同。创建线程会减慢计时器,因此您可以使用 WaitableTimer,它总是在同一个线程上运行。您可以使用 Thread.Sleep 方法代替 WaitableTimer:

    Thread.CurrentThread.Priority = Priority.High; //If time is really critical
    Thread.Sleep (1000 - DateTime.Now + 50); //Make bound = 1s
    while (SomeBoolCondition)
    {
      Thread.Sleep (980); //1000 ms = 1 second, but something ms will be spent on exit from Sleep
      //Here you write your code
    }
    

    它会比计时器工作得更快。

    【讨论】:

    • Thread.Sleep (1000 - DateTime.Now + 50);它不会接受这句异常抛出,因为“运算符'-'不能应用于'int'和'System.DateTime'类型的操作数”
    • 哦,我忘了毫秒 - 当然是 DateTime.Now.Milliseconds。 50 - 是 X,必须通过实践来选择。
    猜你喜欢
    • 2012-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-13
    相关资源
    最近更新 更多