【问题标题】:Simulation using timers without waiting无需等待即可使用计时器进行模拟
【发布时间】:2018-11-08 05:56:55
【问题描述】:

我正在C# 中编写一个基本模拟,从概念上讲,将其设计为多个计时器以从大约半秒到多秒的不同间隔触发事件是最简单的。我用System.Timers.Timer 做了一个粗略的草稿,效果很好。

但是,这只是一个模拟,所以我不想等待!有没有办法立即触发接下来会触发的Timer?

或者这可能是错误的方法,我应该像explained here 那样手动做一些事情(迭代Dictionary 的延迟)?这样的模拟有更好的模式吗?

【问题讨论】:

  • 当然,不要使用计时器。说真的,你的计时器处理程序的主体应该什么都不做,只是调用另一个你可以随时调用的方法。例如OnTimer1() { DoSomething1() }。如果你想立即调用它直接调用DoSomething1()

标签: c# timer simulation


【解决方案1】:

解决此问题的一种方法是使用待处理事件的SortedList(按其“到期日期”排序)并使用足够频繁触发的计时器以满足您想要工作的时间间隔类型(例如,这里每 250 毫秒一次就足够了)。

每次(单个)计时器触发时,它都会检查列表的前面,如果前面的项目过去有到期日期,那么我们将项目出列并安排它运行(无论你在计时器线程本身上运行事件,或者例如启动新的Tasks 来执行它们,这在一定程度上取决于事件是否需要并行发生以及事件处理需要多长时间。

通常,每个事件对象都会在其结构中嵌入某种Action,因此这个调度代码可以非常简单。重复事件可以将它们的“下一次”执行排入队列,作为它们自己操作的一部分,或者您可以选择让计时器线程采取另一种形式的操作。 (如果您正在执行并行执行,则第二种模型往往会更好地工作,因为它只是与事件队列交互的计时器线程,因此不需要锁定)。

最后,如何更频繁地运行事务?完全放弃计时器,只是不断地从队列中取出项目,忽略它们的到期日期。

【讨论】:

  • 我想我的问题的重点是生成序列是令人讨厌的部分,因为某些事件会在其他事件触发一次之前触发几次。让 Timer 处理排序将使我更具声明性,并使我免于编写自己的逻辑以在排序列表中生成事件 - 我绝对可以这样做,我宁愿不重新发明那部分。我还假设将有一种模拟技术可用于帮助测试 Timer 交互,生成序列而没有真实世界的延迟,但顺序正确。
  • @NickP - 正如我在第三段中提到的那样,你最终会得到类似于dequeue front event. Grab Action. If it's a recurring event, add the interval to the due date and enqueue. Run the action 的核心循环。如果入队最终将此事件放回队列的前面,那就这样吧。我没有看到那里的复杂性。
  • 我想我第一次忽略了那部分 - 这听起来绝对是一个足够简单的解决方案,如果我仍然需要它,Timer 的想法允许实时延迟。我会简短地介绍一下。
  • @Damien_The_Unbeliever 我不是 C# 程序员,所以请原谅我的无知。 SortedList 是否对数据进行完全排序?如果是这样,优先级队列实现会更好地实现可伸缩性。优先级队列是离散事件模拟建模中使用的标准方法,因为焦点始终放在将发生的下一个事件是什么,即发生时间最短的事件。您不需要在以后的事件中使用完整的排序属性。
  • @pjs - 我知道 .NET 中没有更具体的优先级队列集合。 SortedX 集合是最接近的。这就是我选择SortedList的原因。
猜你喜欢
  • 1970-01-01
  • 2015-08-25
  • 2012-07-12
  • 1970-01-01
  • 2021-03-05
  • 2021-05-07
  • 1970-01-01
  • 1970-01-01
  • 2014-11-04
相关资源
最近更新 更多