Author Topic: TTimer problem  (Read 20317 times)

radioman

  • New Member
  • *
  • Posts: 33
TTimer problem
« on: April 03, 2012, 09:05:43 pm »
Hello!

I'm having a strange problem with TTimer.

My form uses a TTimer to repeat a task every minute (Timer1.interval:=60000). But when running the program, I get time intervals slightly less than a minute. For example, the task was repeated on these times:

2012-04-03 16:47:02
2012-04-03 16:48:02
2012-04-03 16:49:01
2012-04-03 16:50:01
2012-04-03 16:51:01
2012-04-03 16:52:01
2012-04-03 16:53:01
2012-04-03 16:54:01
2012-04-03 16:55:00
2012-04-03 16:56:00
2012-04-03 16:57:00
2012-04-03 16:58:00
2012-04-03 16:59:00
2012-04-03 17:00:00
2012-04-03 17:00:59
2012-04-03 17:01:59
2012-04-03 17:02:59
2012-04-03 17:03:59
2012-04-03 17:04:59
2012-04-03 17:05:59
2012-04-03 17:06:58
2012-04-03 17:07:58
2012-04-03 17:08:58
2012-04-03 17:09:58
2012-04-03 17:10:58
2012-04-03 17:11:57
2012-04-03 17:12:57
2012-04-03 17:13:57
2012-04-03 17:14:57
2012-04-03 17:15:57
2012-04-03 17:16:57
2012-04-03 17:17:56
2012-04-03 17:18:56
2012-04-03 17:19:56

The effective time interval seems to be something like 59800 milliseconds.

Any ideas?

Thanks in advance!

Rails

  • Guest
Re: TTimer problem
« Reply #1 on: April 03, 2012, 09:16:26 pm »
TTimer is not precise. It only gives rough approximations and is affected by system load. For a precise timer, try http://wiki.lazarus.freepascal.org/EpikTimer.
« Last Edit: April 03, 2012, 09:18:17 pm by Rails »

User137

  • Hero Member
  • *****
  • Posts: 1791
    • Nxpascal home
Re: TTimer problem
« Reply #2 on: April 03, 2012, 09:22:07 pm »
If you insist on using TTimer, you can set it use interval 1000 and do something like:
Code: [Select]
  private // TForm1 variables
    minuteTimer: TDateTime;

formcreate:
  minuteTimer := Now;

procedure Timer1OnTimer(Sender: TObject);
begin
  if Now>=minuteTimer then begin
    minuteTimer := minuteTimer + 1/24/60;
    // Do something every minute

  end;
end;

radioman

  • New Member
  • *
  • Posts: 33
Re: TTimer problem
« Reply #3 on: April 03, 2012, 09:51:01 pm »
Googling a bit I discovered the 1/18 seconds resolution of the basic timer, so I will test both solutions to see what is the best fit to my needs.

Thank you!

radioman

  • New Member
  • *
  • Posts: 33
Re: TTimer problem
« Reply #4 on: April 13, 2012, 06:30:39 pm »
Just for your information, I tried a Delphi component called HiResTimer, wich is almost a direct replacement of TTimer and worked perfectly: The repetitive task is executed always +/- 2 milliseconds from the desired time.

Just nice!

User137

  • Hero Member
  • *****
  • Posts: 1791
    • Nxpascal home
Re: TTimer problem
« Reply #5 on: April 13, 2012, 06:50:30 pm »
There's small difference to resource use for different methods. High res timer will be constantly doing time queries and comparisons, whereas TTimer will sleep the time. The code i gave up earlier is very lightweight solution, and will keep 1 second accuracy even if its let run for many years straight. Setting interval to 100 would give 100ms accuracy but cause slightly more stress for OS. Although not anywhere near as much as high performance timing.

The accuracy i mean is not "additive" sort that would cause total time to increase, but its "balancing". Some event may add a second, and other might remove it. Overall effect is that average interval is exactly 60000ms.

ludob

  • Hero Member
  • *****
  • Posts: 1173
Re: TTimer problem
« Reply #6 on: April 13, 2012, 07:11:06 pm »
Quote
High res timer will be constantly doing time queries and comparisons, whereas TTimer will sleep the time
Not if radioman is talking about the THiResTimer found here http://www.programmersheaven.com/download/2818/1/ZipView.aspx. It is using the windows multimedia timer and does a WaitForSingleObject. No time queries and comparisons.
Downside of this unit is that the WaitForSingleObject and therefor the OnTimer event is done from a separate thread. This complicates updating the GUI from OnTimer. But then again, who wants to update the gui from a hi res timer ;)

radioman

  • New Member
  • *
  • Posts: 33
Re: TTimer problem
« Reply #7 on: April 13, 2012, 07:29:05 pm »
Quote
High res timer will be constantly doing time queries and comparisons, whereas TTimer will sleep the time
Not if radioman is talking about the THiResTimer found here http://www.programmersheaven.com/download/2818/1/ZipView.aspx.

Yes, that is.

It is using the windows multimedia timer and does a WaitForSingleObject. No time queries and comparisons. Downside of this unit is that the WaitForSingleObject and therefor the OnTimer event is done from a separate thread. This complicates updating the GUI from OnTimer. But then again, who wants to update the gui from a hi res timer ;)

Me  O:-)

In fact it appears to work nicely: The OnTimer get data from an external logging system and updates the form.

Any better way to do this?

ludob

  • Hero Member
  • *****
  • Posts: 1173
Re: TTimer problem
« Reply #8 on: April 13, 2012, 08:20:54 pm »
Quote
Me  O:-)

In fact it appears to work nicely: The OnTimer get data from an external logging system and updates the form.

Any better way to do this?
Then you are lucky. Updating the GUI from a thread is not really supported.
Use the the hires timer to get the data from the logging system and store it in a buffer (a circular buffer for example, they are fairly easy to make thread safe). Do as little as possible in the hires timer event because it is executed a lot of times. Use a second TTimer to read the data from the buffer and update the form at a much lower frequency.
« Last Edit: April 13, 2012, 08:22:41 pm by ludob »

User137

  • Hero Member
  • *****
  • Posts: 1791
    • Nxpascal home
Re: TTimer problem
« Reply #9 on: April 13, 2012, 08:25:19 pm »
I assumed he set highrestimer on 1 minute interval. That wouldn't require another timer, and it'd defeat the purpose of the timer in the first place.

radioman

  • New Member
  • *
  • Posts: 33
Re: TTimer problem
« Reply #10 on: April 13, 2012, 08:48:04 pm »
Not exactly. The data is logged from the external device each second (1000 ms exactly!) and then there are some functions to get averages, maximun and minimun, and other information.

Each 60, 120, 180, etc calls to OnTimer (1, 2, 3... minutes) data is stored on disk, but UI is updated each second.

I checked the code and both threads access many common places, so this is a perfect example of how a small bug (irregular timming) ends with a total rewrite of the application. Damn it!

KpjComp

  • Hero Member
  • *****
  • Posts: 680
Re: TTimer problem
« Reply #11 on: April 13, 2012, 09:16:57 pm »
Quote
ends with a total rewrite of the application

Not sure you need a total rewrite  :-\

I'd go with User137 idea, you could set the timer to 100ms, so over a minute you'd be only about +-0.16% out.  You could of course set to 1ms, but I doubt it would make much difference.  And like User137 pointed out it's not going to go out of sync either.  eg. in 5 days time it's still going to be hitting the correct time down to the second.

Also you then don't need to worry about Threading synchronization, and best of all your application is easer to port to other platforms like linux etc.

radioman

  • New Member
  • *
  • Posts: 33
Re: TTimer problem
« Reply #12 on: April 13, 2012, 11:02:06 pm »
I'd go with User137 idea, you could set the timer to 100ms, so over a minute you'd be only about +-0.16% out.  You could of course set to 1ms, but I doubt it would make much difference.  And like User137 pointed out it's not going to go out of sync either.  eg. in 5 days time it's still going to be hitting the correct time down to the second.

I tested it but timming is not correct. The last second digit is jumping constantly +/- 1 digit.

For me now it is clear HiResTimer is "the" solution for this application. I have one program running nicely with the UI being updated within the hirestimer thread. I can ignore it and go with the application and see if it makes any problem in the real world or I can redesign it entirely. A hard decission ;-)

It's sure I will need to improve it in a near future so a total rewrite is not as bad as it sounds...

I'll see. Thank you!

User137

  • Hero Member
  • *****
  • Posts: 1791
    • Nxpascal home
Re: TTimer problem
« Reply #13 on: April 13, 2012, 11:12:14 pm »
If by digit you mean 1 second accuracy, that shouldn't happen at all if you use interval 100. Maybe even 200 or 500 should still execute the event on same second every time.

I modified the code above to have frequency of 5 seconds instead of 1 minute, because i don't want to wait for a hour for a test  :P Anyway, for 6 minutes with 500 interval it gave a steady stream of 2 and 7 ending numbers, meaning that it never failed:

Code: [Select]
14.4.2012 0:14:22
14.4.2012 0:14:27
14.4.2012 0:14:32
14.4.2012 0:14:37
14.4.2012 0:14:42
14.4.2012 0:14:47
14.4.2012 0:14:52
14.4.2012 0:14:57
14.4.2012 0:15:02
14.4.2012 0:15:07
14.4.2012 0:15:12
14.4.2012 0:15:17
14.4.2012 0:15:22
14.4.2012 0:15:27
14.4.2012 0:15:32
14.4.2012 0:15:37
14.4.2012 0:15:42
14.4.2012 0:15:47
14.4.2012 0:15:52
14.4.2012 0:15:57
14.4.2012 0:16:02
14.4.2012 0:16:07
14.4.2012 0:16:12
14.4.2012 0:16:17
14.4.2012 0:16:22
14.4.2012 0:16:27
14.4.2012 0:16:32
14.4.2012 0:16:37
14.4.2012 0:16:42
14.4.2012 0:16:47
14.4.2012 0:16:52
14.4.2012 0:16:57
14.4.2012 0:17:02
14.4.2012 0:17:07
14.4.2012 0:17:12
14.4.2012 0:17:17
14.4.2012 0:17:22
14.4.2012 0:17:27
14.4.2012 0:17:32
14.4.2012 0:17:37
14.4.2012 0:17:42
14.4.2012 0:17:47
14.4.2012 0:17:52
14.4.2012 0:17:57
14.4.2012 0:18:02
14.4.2012 0:18:07
14.4.2012 0:18:12
14.4.2012 0:18:17
14.4.2012 0:18:22
14.4.2012 0:18:27
14.4.2012 0:18:32
14.4.2012 0:18:37
14.4.2012 0:18:42
14.4.2012 0:18:47
14.4.2012 0:18:52
14.4.2012 0:18:57
14.4.2012 0:19:02
14.4.2012 0:19:07
14.4.2012 0:19:12
14.4.2012 0:19:17
14.4.2012 0:19:22
14.4.2012 0:19:27
14.4.2012 0:19:32
14.4.2012 0:19:37
14.4.2012 0:19:42
14.4.2012 0:19:47
14.4.2012 0:19:52
14.4.2012 0:19:57
14.4.2012 0:20:02
14.4.2012 0:20:07

Oh, but if you first time (with 500 millisecond interval, and 5 second delay) is like:
0:50:45:990
Then next execution might happen anywhere from
0:50:50:990 - 0:50:51:490 (+inaccuracy of TTimer)

Second time running the app gave bit like that:
Code: [Select]
14.4.2012 0:28:07
14.4.2012 0:28:11
14.4.2012 0:28:16
14.4.2012 0:28:21
14.4.2012 0:28:26
14.4.2012 0:28:32
14.4.2012 0:28:37
14.4.2012 0:28:42
14.4.2012 0:28:46
14.4.2012 0:28:51
14.4.2012 0:28:56
14.4.2012 0:29:01
14.4.2012 0:29:07
14.4.2012 0:29:12
14.4.2012 0:29:17
14.4.2012 0:29:21
14.4.2012 0:29:26
14.4.2012 0:29:31
14.4.2012 0:29:36
14.4.2012 0:29:42
14.4.2012 0:29:47
14.4.2012 0:29:52
14.4.2012 0:29:56
14.4.2012 0:30:01
14.4.2012 0:30:06
14.4.2012 0:30:11
14.4.2012 0:30:17
14.4.2012 0:30:22
14.4.2012 0:30:27
14.4.2012 0:30:31
14.4.2012 0:30:36
14.4.2012 0:30:41
14.4.2012 0:30:46
14.4.2012 0:30:52
14.4.2012 0:30:57
14.4.2012 0:31:02
14.4.2012 0:31:06
14.4.2012 0:31:11
14.4.2012 0:31:16
Lower the interval, the better precision. Just know that difference between the executed events can only be higher by the interval, not whole second... if you know what i meant...

Sorry, many edits to this post. Wrote things wrong.
« Last Edit: April 13, 2012, 11:38:03 pm by User137 »

radioman

  • New Member
  • *
  • Posts: 33
Re: TTimer problem
« Reply #14 on: April 14, 2012, 12:03:48 am »
Thank you for your interest, but that "last second digit jump" was the start of the bug, so I decided I will use the HiResTimer, who works really nice!

My HiResTimer was in a directory in my hard disk inside a zip with a readme.1st file:

Quote
This TTimer replacement uses the high resolution timing capabilities of
the MMSystem to provide timing far more precise than those possible with
standard Windows's timer resources.  It also illustrates the use of
Delphi 2.0's  TThread class, and the use of a Win32 event for thread
synchronization
.   Freeware with source code.

Provided by
Silicon Commander Games
http://www.silicmdr.com

Sorry if this question is a silly one because I have very little experience with Win32API and threads but:

Is possible this component to be thread safe?


The program is running continuosly since 8 hours ago without any single problem and exquisite temporization in a far than idle computer.

How can I force a thread collision in the LCL? Any ideas?

 

TinyPortal © 2005-2018