Recent

Author Topic: TTimer interval does not accept cardinal integer input  (Read 2521 times)

Muso

  • Sr. Member
  • ****
  • Posts: 356
TTimer interval does not accept cardinal integer input
« on: September 20, 2019, 01:05:08 pm »
According to the documentation of TTimer:
https://lazarus-ccr.sourceforge.io/docs/lcl/extctrls/ttimer.html
the interval is the time in milliseconds in the range of Cardinal integer.
But with this code

Code: Pascal  [Select][+][-]
  1. OverallTimer.Interval:= 4294967294;
  2. OverallTimer.Enabled:= True;

I get the exception EOutOfResources in the procedure TCustomTimer.UpdateTimer;

I played with the timer interval and it only accepts SIGNED integer, so only half of Cardinal. Is this a bug in the TCustomTimer implementation or do I have to do something special?
« Last Edit: September 20, 2019, 01:09:24 pm by Muso »

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: TTimer interval does not accept cardinal integer input
« Reply #1 on: September 20, 2019, 01:21:24 pm »
Hi!

MaxDword = 4294967295 as Timer.Interval results in more then 49 days between two ticks.
MaxInteger results in ~25 days.

Do you really need a timer for an event every month?

It might be a bug, but not one for the real live.

Winni

rvk

  • Hero Member
  • *****
  • Posts: 6111
Re: TTimer interval does not accept cardinal integer input
« Reply #2 on: September 20, 2019, 01:29:20 pm »
The problem is that in the Windows widgetset the Interval is an Integer:

Code: Pascal  [Select][+][-]
  1. function TWin32WidgetSet.CreateTimer(Interval: integer; TimerFunc: TWSTimerProc) : THandle;

I'm not sure what the official documentation says about the maximum Interval.
The fact Interval is a Cardinal doesn't mean it is supposed to contain and handle the maximum amount possible.

(Think about a variable called AngleInDegrees: Integer. You won't ever put anything that high into it.)

Edit: Looking further at the Windows API.

Quote
uElapse
Type: UINT
The time-out value, in milliseconds.
If uElapse is less than USER_TIMER_MINIMUM (0x0000000A), the timeout is set to USER_TIMER_MINIMUM. If uElapse is greater than USER_TIMER_MAXIMUM (0x7FFFFFFF), the timeout is set to USER_TIMER_MAXIMUM.
https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-settimer

So USER_TIMER_MAXIMUM is 0x7FFFFFFF (is 2.147.483.647).

So the TTimer.Interval could have been an Integer regarding Windows API. But I'm not sure if the same goes for Linux. Maybe there it can hold an unsigned Integer (Cardinal).
« Last Edit: September 20, 2019, 01:33:58 pm by rvk »

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: TTimer interval does not accept cardinal integer input
« Reply #3 on: September 20, 2019, 01:52:39 pm »
In Linux MaxDword as value for Timer.Interval is accepted without problems. So it is Widgetset dependent.

Off topic. But near: Just startetd to laugh, when I remembered the "Windows 49 day bug" - 20 years ago. Windows used as server 24/7 crashed all 49 days:
https://www.cnet.com/news/windows-may-crash-after-49-7-days/


Winni

Muso

  • Sr. Member
  • ****
  • Posts: 356
Re: TTimer interval does not accept cardinal integer input
« Reply #4 on: September 20, 2019, 02:12:56 pm »
The problem is that in the Windows widgetset the Interval is an Integer:
So USER_TIMER_MAXIMUM is 0x7FFFFFFF (is 2.147.483.647).

Many thanks. So I have to accept this.
As workaround I will use 2 timers.

Do you really need a timer for an event every month?

The background is that I use my program as frontend to control an Arduino. We need to have an overall runtime for months. Within that time actions start every day. So the problem is the overall time. The timer of the Arduino is a longint (unsigned 32bit int) therefore I thought that 1192 hours overall runtime are possible.

But OK, maybe we must  switch to a 64bit solution for the controller hardware anyway.

rvk

  • Hero Member
  • *****
  • Posts: 6111
Re: TTimer interval does not accept cardinal integer input
« Reply #5 on: September 20, 2019, 02:20:04 pm »
Within that time actions start every day. So the problem is the overall time.
I'm still not sure what timer you set for 1192 hours?

TTimers are for executing some procedure after a given time. There are not for 'keeping time'. So what procedure needs to run after 1192 hours after start of your program? And how do you handle a restart (in which the timer would start again)?

If it's just so you can 'keep time' then you can just better use the clock (for example GetTickCount64).

And if it's to execute procedures at a certain time far in the future, you can just save the datetimes and check them in a TTimer with Interval 1000 (1 second) of 10000 (for 10 seconds).

valdir.marcos

  • Hero Member
  • *****
  • Posts: 1106
Re: TTimer interval does not accept cardinal integer input
« Reply #6 on: September 20, 2019, 02:31:08 pm »
Within that time actions start every day. So the problem is the overall time.
I'm still not sure what timer you set for 1192 hours?
Elapsed time, like [HH] on LibreOffice Calc and Microsoft Excel cell format?

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: TTimer interval does not accept cardinal integer input
« Reply #7 on: September 20, 2019, 02:38:19 pm »
Just an example:

Set Timer1.Interval to 1000.

Code: Pascal  [Select][+][-]
  1. Var Seconds: Integer = 0;
  2.       Days : Integer = 0;
  3.  
  4. Procedure TForm1.Timer1Timer(Sender: TObject);
  5. begin
  6. Inc(Seconds);
  7. label1.Caption := IntToStr(seconds);
  8. if Seconds mod 3600 = 0  then // do something everyHour
  9.    DoItEveryHour;
  10. if seconds = 86400 then // one day
  11. begin
  12. inc(days);
  13. seconds := 0;
  14. Timer1.Enabled := false;
  15. Timer1.Enabled := true; // reinitializes the timer
  16. end;
  17.  
  18.  


Winni
« Last Edit: September 20, 2019, 02:42:42 pm by winni »

rvk

  • Hero Member
  • *****
  • Posts: 6111
Re: TTimer interval does not accept cardinal integer input
« Reply #8 on: September 20, 2019, 02:45:22 pm »
Within that time actions start every day. So the problem is the overall time.
I'm still not sure what timer you set for 1192 hours?
Elapsed time, like [HH] on LibreOffice Calc and Microsoft Excel cell format?
You can't use TTimer for elapsed time (there is no way to query the elapsed time in TTimer).

The only reason to use TTimer is to execute a procedure i.e. 1192 from now. But I don't see a real use for this. If you restart you would need to recalculate how much time has past and set a timer for 1192 - elapsed hours. That doesn't really seem useful. If that's the case it would be better to set the exact date and time you want to execute something and set a TTimer for say 10 seconds, and then check each 10 seconds if that TDateTime is arrived.

But maybe I'm missing something in why the TTimer is used.

Muso

  • Sr. Member
  • ****
  • Posts: 356
Re: TTimer interval does not accept cardinal integer input
« Reply #9 on: September 20, 2019, 02:55:33 pm »
I'm still not sure what timer you set for 1192 hours?
And if it's to execute procedures at a certain time far in the future, you can just save the datetimes and check them in a TTimer with Interval 1000 (1 second) of 10000 (for 10 seconds).

You are right. Stupid me. I made a fatal mistake. Neither in the microcontroller nor in my Lazarus frontend, I really need a timer that runs the overall time.

The task is that a laboratory guy starts the machine and the machine then running for months. my program should indicate that it is running, nothing more. The microcontroller timer is reset on every new action and there will be actions every few hours.
So I will now try out the solutions proposed here and report back.

Many thanks to you all! I am amazed how quick I got very valuable replies.

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1312
    • Lebeau Software
Re: TTimer interval does not accept cardinal integer input
« Reply #10 on: September 20, 2019, 09:05:27 pm »
it would be better to set the exact date and time you want to execute something and set a TTimer for say 10 seconds, and then check each 10 seconds if that TDateTime is arrived.

On Windows at least, rather than polling the current time at regular intervals, I would either:

- set a Waitable Timer Object to the exact target time, and then have a thread wait on that object and notify the app when the object is signaled.

- create a Scheduled Task that calls back into my app when the target time is reached.
« Last Edit: September 20, 2019, 09:08:27 pm by Remy Lebeau »
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

ASerge

  • Hero Member
  • *****
  • Posts: 2223
Re: TTimer interval does not accept cardinal integer input
« Reply #11 on: September 20, 2019, 10:04:37 pm »
- set a Waitable Timer Object to the exact target time, and then have a thread wait on that object and notify the app when the object is signaled.
In LCL (Windows) already has a technique for waiting for kernel objects, so there is no need to create a thread.

Thaddy

  • Hero Member
  • *****
  • Posts: 14205
  • Probably until I exterminate Putin.
Re: TTimer interval does not accept cardinal integer input
« Reply #12 on: September 20, 2019, 10:26:22 pm »
I am quite sure Remy means to have a worker thread waiting for the kernel object, not block the main thread.
Specialize a type, not a var.

jamie

  • Hero Member
  • *****
  • Posts: 6091
Re: TTimer interval does not accept cardinal integer input
« Reply #13 on: September 21, 2019, 12:06:37 am »
Why can't a simple TDateTime process be used? You can use one of the DaysBEtween etc.. functions
The only true wisdom is knowing you know nothing

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1312
    • Lebeau Software
Re: TTimer interval does not accept cardinal integer input
« Reply #14 on: September 21, 2019, 12:10:38 am »
I am quite sure Remy means to have a worker thread waiting for the kernel object, not block the main thread.

Correct.  Either a manual thread that uses WaitForSingleObject() (or WaitForMultipleObjects() so the thread can use a second object to wait on for termination requests), or an OS-managed thread from RegisterWaitForSingleObject().
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

 

TinyPortal © 2005-2018