Recent

Author Topic: Timer priority  (Read 4013 times)

BLL

  • Sr. Member
  • ****
  • Posts: 276
Timer priority
« on: January 19, 2017, 09:28:08 pm »
Hi
Can someone help me? My application has 2 timers. One is the normal TTimer one with a period of 1s. However, sometimes the fetching of data and its processing and delay can take longer than the period, which lead to random seizures. A good suggestion from a forum member suggested disabling the timer on entering its function and re-enabling at the end, eg.

Code: Pascal  [Select][+][-]
  1. procedure TMainForm.ClockTimer(TSender:Object);
  2. begin
  3.  Clock.Enabled := false;
  4.  //fetch, process & display a lot of data
  5.  Clock.Enabled := true;
  6. end;

I then have a second timer running in its own thread, also with a period of 1s, called uThreadTimer. The code for this was also provided by a helpful soul on the forum. This timer just displays time and date info.

However, the problem is that often the clock display misses a second or more. The time is correct, but the display does not increment every second. It therefore appears that there is interaction between the 2 timers, even though they are running in separate threads?
Is it possible to give uThreadTimer a greater priority and would this help?

Thanks

Brian

RasPi model 3, fpc3.0.0, lazarus 1.7, SVN Rev 51308, arm-linux-gtk2

Thaddy

  • Hero Member
  • *****
  • Posts: 14373
  • Sensorship about opinions does not belong here.
Re: Timer priority
« Reply #1 on: January 19, 2017, 09:38:02 pm »
No.
The ratio is that you have to synchronize the threads with the main thread for display purposes.
That is what is causing the delay..
Note that a display of such a construct is and always be an approximation of what really happened.
A Display is slow, even by today's standards.
What I would do is put BOTH timers in their own thread.
Let them push their results in a TThreadedQueue and pop those off the Queue in the OnIdle event and then display.
(Note: Idle is Idle for the main thread only!, but you can also maintain a third timer that does the popping in the main thread)

If you do it like that, you won't have to synchronize either...
« Last Edit: January 19, 2017, 09:43:21 pm by Thaddy »
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

balazsszekely

  • Guest
Re: Timer priority
« Reply #2 on: January 19, 2017, 09:39:52 pm »
As far as I can see you're blocking the main thread. You should move the "fetching of data and its processing" to a separate worker thread.

Thaddy

  • Hero Member
  • *****
  • Posts: 14373
  • Sensorship about opinions does not belong here.
Re: Timer priority
« Reply #3 on: January 19, 2017, 09:41:13 pm »
@GetMem
Yup. See my remarks. Any comments?
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

balazsszekely

  • Guest
Re: Timer priority
« Reply #4 on: January 19, 2017, 09:54:39 pm »
@Thaddy
I'm not sure why the OP needs two timers in the first place. With that threaded timer you can measure more then one time simultaneously. Anyway the original question was:
Quote
Is it possible to give uThreadTimer a greater priority and would this help?
My answer to the first part is yes, but it would not help.

BLL

  • Sr. Member
  • ****
  • Posts: 276
Re: Timer priority
« Reply #5 on: January 19, 2017, 10:12:24 pm »
Hi Guys

Thanks for the suggestions but they go over my head!
I don't know how to use a TThreadedQueue to do what Thaddy is sugesting!

I can certainly set up another thread, but after that, I'm lost!

Brian

balazsszekely

  • Guest
Re: Timer priority
« Reply #6 on: January 19, 2017, 10:23:55 pm »
I think in your case the easiest solution is to refresh your main application, by processing(as soon as possible) the messages from the event queue. Like this:
Code: Pascal  [Select][+][-]
  1. procedure TMainForm.ClockTimer(TSender:Object);
  2. begin
  3.   Clock.Enabled := false;
  4.   //fetch, process & display a lot of data
  5.   while [fetching/processing] do
  6.   begin
  7.     Application.ProcessMessages;
  8.     [fetch/process/display]
  9.   end;  
  10.   Clock.Enabled := true;
  11. end;

PS: Please note this is not the ideal solution but might work. Ideally you should move the fetch/process/ part to a thread then by synchronise/queue update the main thread.
« Last Edit: January 19, 2017, 10:28:12 pm by GetMem »

BLL

  • Sr. Member
  • ****
  • Posts: 276
Re: Timer priority
« Reply #7 on: January 20, 2017, 07:41:36 pm »
Hi Getmem

Thanks for the suggestion. I have implemented this and whereas it has improved matters, it still isn't quite right. Some displayed seconds change very quickly, whereas others don't change so fast!

Brian

User137

  • Hero Member
  • *****
  • Posts: 1791
    • Nxpascal home
Re: Timer priority
« Reply #8 on: January 21, 2017, 06:29:11 am »
Simple solution would be using smaller interval for TTimer such as 100. Use Now function to get current time and compare it to last time that second was elapsed. Once the difference is over a second, execute the code and add 1 second to the comparison value.

Code: Pascal  [Select][+][-]
  1. - formcreate:
  2. secondTimer:=Now+second1; // Optionally round to nearest second
  3.  
  4. - timer:
  5. if Now>secondTimer then begin
  6.   secondTimer:=secondTimer+second1;
  7.   // ... do stuff here every second
  8. end;
It is a kind of code that should remain accurate within 100ms (interval) even if you let the TTimer run for several weeks straight.

How to get second1 value? Look in the unit that has time functions, maybe it was  Encodetime().

And if you have a custom time function, you would use that instead of Now.
« Last Edit: January 21, 2017, 06:35:24 am by User137 »

BLL

  • Sr. Member
  • ****
  • Posts: 276
Re: Timer priority
« Reply #9 on: January 21, 2017, 10:51:19 am »
Hi User137
That's interesting - I shall go and try it.

Thanks

Brian

 

TinyPortal © 2005-2018