Jump to content
Sonjli

Scheduled tasks at system time

Recommended Posts

Hi,

I need to schedule some actions when the time arrives. Something like Windows scheduler does.

For example at 12.00am of every day I have to post a rest call on a web site, or at 2.00pm another task.

I know it is simple to do it with a standard timer or a polling on system time, but is there a smart solution with OTL?

 

Thanks in advance.

Share this post


Link to post

I've no experience with OTL but a primitive solution comes to mind - launch a task with wait

ev := CreateEvent(...)

if WaitForSingleObject (ev, ScheduledTime-CurrentTime) = WAIT_TIMEOUT then

... do something scheduled

 

to be able to cancel the wait, additional waitable object will be required and WaitForMultipleObjects instead

Share this post


Link to post
4 hours ago, David Heffernan said:

Why don't you use the system scheduler? 

Because I need to be in strict control with the scheduling and I am in cross development (Linux and Windows at least).

1 hour ago, Fr0sT.Brutal said:

I've no experience with OTL but a primitive solution comes to mind - launch a task with wait

ev := CreateEvent(...)

if WaitForSingleObject (ev, ScheduledTime-CurrentTime) = WAIT_TIMEOUT then

... do something scheduled

 

to be able to cancel the wait, additional waitable object will be required and WaitForMultipleObjects instead

Interesting... any example? I know I can do something like this in OTL, so a "standard" example could help me to figure out.

Share this post


Link to post
2 hours ago, Sonjli said:

Because I need to be in strict control with the scheduling and I am in cross development (Linux and Windows at least).

Interesting... any example? I know I can do something like this in OTL, so a "standard" example could help me to figure out.

None except that code snippet but it's trivial. For x-platform you can use System.SyncObjs.TEvent.WaitFor. I couldn't find x-platform method to wait for multiple objects so to cancel the wait you'll have to reset each waitable object (so you'll have to keep a list of them... code becomes less and less short & trivial 🙂 )

Edited by Fr0sT.Brutal
  • Like 1

Share this post


Link to post

Write a simple scheduler - i,e, a collection of tasks and when / how often you want to run them. 

Oneshot immediately, oneshot at a specific time, repeating by interval, repeating at fixed points in time, etc.

 

Create a task manager thread that checks the scheduler and queues tasks into a task execution queue. 

You can have a framework of rules such as tasks not being able to run in parallel, or tasks that should not be queued if already in the queue or being executed, etc.

 

The task manager thread also start the tasks from the execution queue and launch them as separate threads at the appropriate time.

You decide how many parallel tasks you can run at a time, and you could even have a task worker thread pool.

 

Share this post


Link to post
1 hour ago, Lars Fosdal said:

"A whole lot of stuff"

 

Is all that part of the OTL? Then I definitely have to look into that.

Share this post


Link to post
23 minutes ago, Sherlock said:

Is all that part of the OTL? Then I definitely have to look into that.

Actually, I wasn't thinking of OTL at all - but that would be worth looking into.

 

I attached a generic scheduler though.  I had to clean out some proprietary code, but not much.

The idea is that the generic type T is an enumerated type like f.x. TJob = (jobUnknown, jobUpdateFiles, jobPublishPage, jobCleanupOldData, jobEtcEtcEtc);

 

The actual task manager is a different story.  It would take me quite some time to "unproprietaryize" that one - and that is really where the work is.

GenericScheduler.pas

  • Thanks 1

Share this post


Link to post

Ohhh, OK. Thanks. I thought I had been sidestepping an extremely powerful library here. :classic_dry:

  • Like 1

Share this post


Link to post
1 hour ago, Lars Fosdal said:

The idea is that the generic type T is an enumerated type like f.x. TJob = (jobUnknown, jobUpdateFiles, jobPublishPage, jobCleanupOldData, jobEtcEtcEtc);

I did exactly the same for mine xD

  • Like 1

Share this post


Link to post

Eventually when you discover all the flaws in your solution you'll come back to using the system scheduler. 

Edited by David Heffernan
  • Like 1
  • Haha 2

Share this post


Link to post
10 hours ago, David Heffernan said:

Eventually when you discover all the flaws in your solution you'll come back to using the system scheduler. 

Do you mean some API functions or taskschd.msc?

Share this post


Link to post

I suspect this is just an interface to scheduler service, so probably not an option for various reasons

Share this post


Link to post

I have this running in a legacy windows service. Much neater stuff available today but it goes like this:

 

A worker thread is kicked in action at an interval. Say 2 minutes. An array or a couple of boolean flags exists.

The parent thread that starts the worker thread is responsible for setting the flags and the worker for clearing them (after successful execution).

Key is that the tread is allowed to finish. It may be a job (check something) that should be done at each thread start.

If the worker crash it will not clear the flag and the job will be run again next time (of course, you should send some kind of alert in this case).

Also if a job is more than 2 minutes (the interval) then if more is required it will be done on the next run.

It uses very basic CriticalSection for the flags.

Of course, this solution is very simple and depending on the needs it may fall short and get messy but for just a couple of different actions it will suffice.

 

HTH,

 

/D

  • Like 1

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×