开发者

Multithreading Task Library, Threading.Timer or threads?

开发者 https://www.devze.com 2023-03-17 20:06 出处:网络
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

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 givin开发者_高级运维g 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?


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:

  • Spawn cancellable tasks with Observable.GenerateWithDisposable and your own Scheduler - check more at Rx 101 Sample
  • Delay tasks with Observable.Delay
  • Wait for tasks with 'Observable.Timeout
  • Compose tasks in any preferable way

Once again you can check more at specified above links.


You should check out Quartz.NET.

Quartz.NET is a full-featured, open source job scheduling system that can be used from smallest apps to large scale enterprise systems.

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.


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

0

精彩评论

暂无评论...
验证码 换一张
取 消