The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My badges

  • Twitter Updates

  • My Flickr Stream

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 2,914 other followers

Some OmniThreadLibrary notes and links

Posted by jpluimers on 2021/07/14

For my link archive:

IOmniTimedTask and the Timed task name

You create a reference like this:

  TimedTask := Parallel.TimedTask.Execute(
    procedure(const task: IOmniTask)
      // ...

In the background, Parallel.TimedTask calls TOmniTimedTask.Create() which calls CreateTask(TOmniTimedTaskWorker.Create(), 'Timed task').Unobserved.Run

The problem is that TOmniTimedTaskWorker is private to the OtlParallel unit, which means you cannot take that call out without also copying that class.

There might be a workaround which I need to research based on the Apply method of IOmniTaskConfig, maybe through Parallel.ApplyConfig. These links might help:


3.15 Timed task

Timed task abstraction creates a threaded timer. To create a Timed task, call Parallel.TimedTask.

See also demos65_TimedTask.


1 FTimedTask := Parallel.TimedTask.Every(5000).Execute(
2  procedure (const task: IOmniTask)
3  begin
4  task.Comm.Send(MSG_WATCHDOG, 'Still alive ...');
5  end;

This code fragment creates a Timed task which every 5 seconds (5000 milliseconds) sends a message MSG_WATCHDOG to its owner.

3.15.1 IOmniTimedTask interface

The Parallel.TimedTask function returns an IOmniTimedTask interface which is used to configure and control a Timed task.

  TOmniTaskDelegate = reference to procedure(const task: IOmniTask);
  IOmniTimedTask = interface
  function Every(interval_ms: integer): IOmniTimedTask;
  function Execute(const aTask: TProc): IOmniTimedTask; overload;
  function Execute(const aTask: TOmniTaskDelegate): IOmniTimedTask; overload;
  procedure ExecuteNow;
  procedure Start; 
  procedure Stop;
  function TaskConfig(const config: IOmniTaskConfig): IOmniTimedTask;
  function Terminate(maxWait_ms: cardinal): boolean; 
  function WaitFor(maxWait_ms: cardinal): boolean;
  property Active: boolean;
  property Interval: integer;

Every sets the timer interval (in milliseconds). Interval must be a positive number. If you set it to a value which is less than or equal to zero, the timer will be disabled. (It is, however, advisable to use Stop or Active := false for this purpose as that more clearly states the intention of the code.)

When a timed task is created, its interval is set to 0 ms.

You can inspect and modify the interval by using the Interval property. Setting an interval by assigning a value to this property (Interval := value;) is equivalent to calling Every(value).

Execute specifies the code that will be called each Interval milliseconds (timer event handler code). This can be a parameter-less anonymous method (or normal procedure, or an object method) or procedure/method/anonymous method accepting one parameter of type IOmniTask which holds the interface of the background task executing the timer method.

After you set an interval (even if the current value is equal to the previous value), the background task will wait for Interval milliseconds before calling the timer event handler code.

If you want to execute timer event handler immediately, call the ExecuteNow method. This will also reset the timer so that next automatic invocation of the timer event handler will occur Interval milliseconds from now.

Start will start (enable) the timer. To stop (disable) the timer call the Stop method. Current state of the timer is available via the Active property.

You can also start/stop a timer by changing the Active property. Setting Active := true is equivalent to calling Start and setting Active := false is equivalent to calling Stop.

A timer is automatically started (enabled) when you call Execute – if and only if the Interval has already been set.

If you want to create a stopped timer with a very small Interval value, it is advisable to use the following pattern:

1 timedTask := Parallel.TimedTask.Execute(SomeCode);
2 timedTask.Stop;
3 timedTask.Interval := 1;

TaskConfig sets up a task configuration block.

Calling Terminate will stop the timed task. If it stops in maxWait_msTrue is returned, False otherwise. WaitFor waits for the task to stop (without commanding it to stop beforehand so you would have to call Terminate before WaitFor) and returns True/False just as Terminate does.

It is usually enough to just set the IOmniTimedTask instance to nil as that effectively calls the Terminate(INFINITE).

I need to do some more research in the WaitFor behaviour in combination with the Interval, especially when the task takes longer than an Interval number of milliseconds.

Some links that might help me with that:


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: