多线程任务库、Threading.Timer 还是线程?
您好,我们正在构建一个可以注册计划任务的应用程序。
每个任务都有一个应该执行的时间间隔 每个任务都应该有一个超时时间 任务数量可以是无限的,但正常情况下约为 100 个。
那么我们有一个需要间隔执行的任务列表,哪些是最好的解决方案?
我已经考虑过为每个任务提供计时器,当计时器到期时,工作将开始,另一个计时器会跟踪超时,因此如果达到超时,另一个计时器将停止线程。
这感觉像是我们过度使用了计时器吗?或者它能起作用吗?
另一个解决方案是为每个任务使用计时器,但是当时间过去时,我们将任务放在一个队列中,该队列将被执行该工作的一些线程读取?
我还应该寻找其他好的解决方案吗?
Hi we are building an application that will have the possibility to register scheduled tasks.
Each task has an time interval when it should be executed
Each task should have an timeout
The amount of tasks can be infinite but around 100 in normal cases.
So we have an list of tasks that need to be executed in intervals, which are the best solution?
I have looked at giving each task their timer and when the timer elapses the work will be started, another timer keeps tracks on the timeout so if the timeout is reached the other timer stops the thread.
This feels like we are overusing timers? Or could it work?
Another solution is to use timers for each task, but when the time elapses we are putting the task on a queue that will be read with some threads that executes the work?
Any other good solutions I should look for?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
没有太多信息,但看起来您也可以考虑 RX - 查看更多信息MSDN.com。
您可以将任务视为生成的事件,应以某种方式组合(安排)。因此,您可以执行以下操作:
Observable.GenerateWithDisposable
和您自己的Scheduler
生成可取消的任务 - 请访问 Rx 101 SampleObservable.Delay
延迟'Observable.Timeout
您可以再次在上面指定的链接中查看更多信息。
There is not too much information but it looks like that you can consider RX as well - check more at MSDN.com.
You can think about your tasks as generated events which should be composed (scheduled) in some way. So you can do the following:
Observable.GenerateWithDisposable
and your ownScheduler
- check more at Rx 101 SampleObservable.Delay
'Observable.Timeout
Once again you can check more at specified above links.
您应该查看 Quartz.NET。
我相信您需要自己实现超时要求,但安排任务所需的所有管道都可以由 Quartz.NET 处理。
You should check out Quartz.NET.
I believe you would need to implement your timeout requirement by yourself but all the plumbing needed to schedule tasks could be handled by Quartz.NET.
我之前做过类似的事情,其中有很多套接字对象需要定期启动和超时。我使用了一个带有“OnStart”和“OnTimeout”事件的“TimedAction”类(由此派生的套接字类等),以及一个处理所有定时操作的线程。该线程维护一个按所需下一个操作的滴答时间排序的 TimedAction 实例列表(增量队列)。 TimedAction 对象通过将它们排队到线程输入队列来添加到列表中。线程在此输入队列上等待超时(这是 Windows,因此管理队列的信号量句柄上的“WaitForSingleObject”),设置为列表中第一项的“需要下一个操作”滴答计数。如果队列等待超时,则调用列表中第一项的相关操作事件,并将该项目从列表中删除 - 然后下一个队列等待将由新的“列表中的第一项”设置,其中包含新的“最近的行动时间”。如果一个新的 TimedAction 到达队列,线程会计算其超时滴答时间(GetTickCount + 对象的毫秒间隔),并将其插入到排序列表中的正确位置(是的,这有时意味着移动大量对象)向上列出列表以腾出空间)。
超时处理程序线程调用的事件不能采取任何冗长的操作,以防止延迟处理其他超时。通常,事件处理程序会设置一些状态枚举,向一些同步对象发送信号或将 TimedAction 排队到其他一些 PC 队列或 IO 完成端口。
这有道理吗?它工作正常,以相当及时和有效的方式在我的服务器中处理数千个定时操作。
我计划进行的一项增强功能是使用具有一组受限超时间隔的多个列表。我的系统中只使用了三个常量超时间隔,因此我可以使用三个列表,每个列表一个间隔。这意味着列表不需要显式排序 - 新的 TimedActions 将始终位于列表的末尾。这将消除在列表中间插入昂贵的对象。我从来没有抽出时间来做这件事,因为我的第一个设计工作得足够好,而且我还有很多其他错误需要修复:(
两件事:
注意 32 位tickCount翻转。
你需要在队列超时块中循环 - 可能有项目在一旦队列超时发生,您需要从列表中删除并触发每个对象的事件,直到新计算的超时时间> 0。这两个具有相同超时滴答计数的对象到达了列表的头部,其中一个被触发,但系统滴答计数已继续,因此下一个对象的计算超时滴答为 -1:无限 我的服务器停止了!正常工作并最终锁定:(
Rgds,
马丁
I have done something like this before where there were a lot of socket objects that needed periodic starts and timeouts. I used a 'TimedAction' class with 'OnStart' and 'OnTimeout' events, (socket classes etc. derived from this), and one thread that handled all the timed actions. The thread maintained a list of TimedAction instances ordered by the tick time of the next action required, (delta queue). The TimedAction objects were added to the list by queueing them to the thread input queue. The thread waitied on this input queue with a timeout, (this was Windows, so 'WaitForSingleObject' on the handle of the semaphore that managed the queue), set to the 'next action required' tick count of the first item in the list. If the queue wait timed out, the relevant action event of the first item in the list was called and the item removed from the list - the next queue wait would then be set by the new 'first item in the list', which would contain the new 'nearest action time'. If a new TimedAction arrived on the queue, the thread calculated its timeout tick time, (GetTickCount + ms interval from the object), and inserted it in the sorted list at the correct place, (yes, this sometimes meant moving a lot of objects up the list to make space).
The events called by the timeout handler thread could not take any lengthy actions in order to prevent delays to the handling of other timeouts. Typically, the event handlers would set some status enumeration, signal some synchro object or queue the TimedAction to some other P-C queue or IO completion port.
Does that make sense? It worked OK, processing thousands of timed actions in my server in a reasonably timely and efficient manner.
One enhancement I planned to make was to use multiple lists with a restricted set of timeout intervals. There were only three const timeout intervals used in my system, so I could get away with using three lists, one for each interval. This would mean that the lists would not need sorting explicitly - new TimedActions would always go to the end of their list. This would eliminate costly insertion of objects in the middle of the list/s. I never got around to doing this as my first design worked well enough and I had plenty other bugs to fix :(
Two things:
Beware 32-bit tickCount rollover.
You need a loop in the queue timeout block - there may be items on the list with exactly the same, or near-same, timeout tick count. Once the queue timeout happens, you need to remove from the list and fire the events of every object until the newly claculated timeout time is >0. I fell foul of this one. Two objects with equal timeout tick count arrived at the head of the list. One got its events fired, but the system tick count had moved on and so the calcualted timeout tick for the next object was -1: INFINITE! My server stopped working properly and eventually locked up :(
Rgds,
Martin