【问题标题】:Multi-threading method for periodic actions周期性动作的多线程方法
【发布时间】:2013-06-20 06:33:31
【问题描述】:

我有一个应用程序需要从不同的模块以每秒一次的周期执行大量操作。 这些动作彼此不相关。 有些动作不是那么重要,可以超过 1 秒。以几秒钟为周期,但对于其他 动作非常重要,它们将在 1 秒内执行。周期(最多延迟 400 毫秒)。

到目前为止,我的开发方法是给每个动作一个计时器,但现在我已经达到了 40 个计时器,我注意到 每个动作的延迟可能很长。

我的问题是,鉴于上述限制,我的应用程序的最佳方法是什么。 何时使用线程,何时使用计时器甚至任务? 也许我什至在错误的框架上,.Net 无法处理这种情况?!

感谢您的帮助, 哈达斯

P.S:也许值得一提的是,所有任务从一开始都是已知的,这意味着我的问题不是 动态添加任务,但决定应用程序的开发方法。

【问题讨论】:

  • 关于这些重要动作——当你有50个这样的动作每1秒触发一次时,预期的行为是什么?您期望 50 个并行操作吗?如果其中一些的运行时间大于 1 秒怎么办?您是否希望在第一个实例尚未完成时启动同一任务的第二个实例?
  • 听起来您正在构建一个实时系统。我认为,这意味着您为这项工作选择了错误的工具。 C#(至少是 Microsoft 的标准版本,带有通常的 GC)适合构建实时系统。
  • @inquisitive,是的,有些动作我想开始,即使它们的最后一个周期没有结束。

标签: multithreading c#-4.0 timer periodic-processing


【解决方案1】:

您可以尝试以下几种方法:

1) 如果没有大量的任务,则将每个任务线程化并运行 'while(true){Sleep(requiredIinterval);task()};'环形。降低运行低优先级任务的线程的优先级,以便它们被高优先级任务抢占。

优点:这个简单的解决方案很容易尝试,可能会满足您的要求。任何任务的多个副本都不可能运行。

缺点:每个任务所花费的时间被添加到 const 间隔中,因此延长了任务之间的时间。对于数千个任务来说,这不是一个好的解决方案。

2) 同上,但在任务前读取wall-time获取开始时间,任务后读取wall-time获取结束时间。如果 (requiredIinterval-(end-start)) 为正,则转换为 ms 并在该间隔内休眠。

优势:每个任务花费的时间不会影响超时,除非它长于所需的时间间隔。任何任务的多个副本都不可能运行。

缺点:对于数千个任务来说,这不是一个好的解决方案。

3) 实现一个增量排序的优先级队列系统。一种方法是为每个优先级使用一个自定义线程池类,再使用一个“timerThread”来运行任务的增量队列。 timerThread 类包含 deltaQueue——一个按超时时间排序的任务集合和一个用于任务的“inputQueue”——一个普通的并发队列。 timerThread 等待信号量,超时设置为 deltaQueue 头部任务的超时时间,如果等待超时,它会删除任务,将其发送到适合其优先级的线程池,然后返回,在 deltaQueue 的新头部获取任务的超时时间,并再次等待信号量。当任何线程池完成任务时,它会将完成的任务排队到 timerThread inputQueue 并发出信号量。然后 timerThread 唤醒,由于等待返回 true,它获取返回的任务并将其重新插入到 deltaQueue 中,以便它的“间隔重新启动”。

优势:每个任务花费的时间不会影响超时,除非它长于所需的时间间隔。任何任务的多个副本都不可能运行。许多“超时任务”的良好解决方案。这些任务只是在 deltaQueue、threadPools 和 inputQueue 中循环,所以很少有 GC 会搞砸时间。

缺点:与其他解决方案相比复杂性。不确定 C# 线程池类是否允许设置池线程优先级 - 您可能必须通过将 blockingCollection 传递给许多显式线程实例来创建自己的线程池类。

4) 我还没有想到的所有其他好的解决方案。

【讨论】:

  • 哇,感谢您的全面回答。星期天上班的第一件事,我会检查你的建议。
猜你喜欢
  • 2014-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多