OnTimer() has a very large delay. How to solve it?

 

I setup a one-second timer. I expect I can receive a signal on OnTimer() every second. But the truth is that there could be a delay. Sometimes the delay can be very large. The recent record is 849 seconds delay.

I'm very surprised with the delay. 

Is there any way to get a reliable timer?

I have attach the codes and screen shot.

#property version   "1.0"
#property copyright "Copyright 2022, Ksana Trading Corp."
#property link      "https://www.ksanatrading.com"

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
   if(!EventSetTimer(1))
      return (INIT_FAILED);
   string msg;
   msg = "Monitoring timer delay...";
   Comment(msg);
   Print(msg);
//--- succeed
   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   EventKillTimer();   
}
//+------------------------------------------------------------------+

void OnTimer()
{
   static datetime last_call=-1;
   datetime now = TimeLocal();
   if(last_call != now)
   {
      int gap = (int)(now-last_call);
      if(last_call!=-1 && gap>=2)
      {
         static int gap_max=0;
         static double gap_total=0;
         static int gap_count=0;
         gap_total += gap;
         gap_count++;
         if(gap>gap_max)
         {
            gap_max=gap;
            string msg;
            msg = StringFormat("Max Delay=%d (s), at %s. delayed %d times, average delay=%.2f (s)",gap_max,
               TimeToString(TimeCurrent(),TIME_DATE|TIME_SECONDS),gap_count,gap_total/gap_count);
            Comment(msg);
            Print(msg);
         }
      }
      last_call = now;
   }
}

 

Timer is reliable, but probably your code don't work correctly.

Do a simple test

void OnTimer()
{
   Print(__FUNCTION__);
}

And you will clearly see it printing a message every 1 second, always.


 

The timer is reliable, but it won't run while it or OnTick is running.
      How To Ask Questions The Smart Way. (2004)
          Don't rush to claim that you have found a bug.
      Questions Not To Ask
          My program doesn't work. I think system facility X is broken.

It is almost always your code.

See my countdown timer (MT4)
          Indicators: Zero Lag Timer - Indices - Articles, Library comments - MQL5 programming forum #8 (2017)

 
Fabio Cavalloni #:

Timer is reliable, but probably your code don't work correctly.

Do a simple test

And you will clearly see it printing a message every 1 second, always.


This way causes too many log. It's hard to find out the delay

 
Longsen Chen #:

This way causes too many log. It's hard to find out the delay

You have to gate it . If it is busy don't let it run. You may "skip" some this way but you wont clog your system 

If you are drawing stuff on the screen you can drop to 44milliseconds too
 
Longsen Chen #:

This way causes too many log. It's hard to find out the delay

One log row for each 1 second, means the timer is reliable and occurs every 1 exact second, as intended to be 
 

In most cases, OnTimer is reliable. However, I did catch cases of large delays. Maybe it's because the Windows system starts too many terminals, and I run a copy software for each terminal. In my specific situation, there are 10 terminals, and the CPU load rate is about 50%. We know that each chart is an independent thread, and an EA that tests timers should have reliable results.

I made modification to the codes to make it simple. But the result is the same. There are delays.

void OnTimer()
{
   static datetime last_call=0;
   static int gap_max=0;
   datetime now = TimeLocal();
   if(last_call != now)
   {
      if(last_call>0)
      {
         int gap = (int)(now-last_call);
         if(gap>gap_max)
         {
            gap_max=gap;
            string msg;
            msg = StringFormat("Max Delay=%d (s), at %s",gap_max,
               TimeToString(TimeLocal(),TIME_DATE|TIME_SECONDS));
            Comment(msg);
            Print(msg);
         }
      }
      last_call = now;
   }
}
Files:
Timer.mq4  3 kb
 
AccurateTimer
AccurateTimer
  • www.mql5.com
Increased accuracy of the standard timer.
 
I don't know, I'm using EA and indicators based on fast timers (<1 second) and the refresh is as expected, never had a single problem.
 
Fabio Cavalloni #:
One log row for each 1 second, means the timer is reliable and occurs every 1 exact second, as intended to be 

I need to test for 24 hours. it will print 24*3600 logs. It's very hard to find out if some seconds are missed.

 
Fabio Cavalloni #:
I don't know, I'm using EA and indicators based on fast timers (<1 second) and the refresh is as expected, never had a single problem.

Your code is very good to get accurate timer only if Ontimer() is called expectedly. What if Ontimer() is not called, especially when system is busy and for 24 hours test.