Event stream. How to control and make the event idle ? (+ solved)

 

There is one problem - I need to make update some function, but faster than MQL on timer - less than 1 second.
Solution - made event sending to myself - EventChartCustom in OnChartEvent.

All works very fast. But the second problem is that the message queue has no time to be cleaned up.

For example when click on the object the event CHARTEVENT_OBJECT_CLICK will come not at once, but only after all previous events will be removed from the queue.
And as you understand the event queue is clogged with EventChartCustom.

Basically, we need to achieve a tightly controlled update of some function, but at the same time

- there was no endless loop like while (true)
- but also that OnChartEvent responds as soon as the chart event happens.

What to do in this situation? Maybe there is another option with EventChartCustom sending control ?

In other words - how to make MQL call some function more than 1 second, but without any queues.

----------

The easiest solution (but with developer involvement) is to allow receiving the next event from the event queue, but without exiting the OnChartEvent function .

I.e., I want all the empty events from my EventChartCustom to be cleaned up in one go. And do not allow to load the queue with left events.

 

If you only send an event when handling OnChartEvent, the queue should logically not overflow. You don't run this event everywhere, do you?

You can also send the event through the event routing. I.e. there is an indicator or other Expert Advisor, which is only needed to send response events to certain events to the sender.

 
TheXpert:

If you only send an event when handling OnChartEvent, the queue should logically not overflow.

No, it just overflows itself. EventChartCustom is called at OnChartEvent. And there is a dense stream of events. On the one hand it's what you need, but on the other hand it takes a long time for chart events to get through.

You can also send the event through the event pad. I.e., there is an induke, or other advisor, which is only needed to send response events to certain events to the sender.

I've thought about it this way, but haven't come up with anything. Describe the exchange scheme?
 
sergeev:
I have thought about it, but have not come up with anything. Please describe the exchange scheme.

We have an indicator (different threads, it may be better). It catches event 1. In the event, it is desirable to pass all the necessary information to be sent back.

Turkey sends event 2 to event 1 sender.

The EA catches event 2 and sends event 1 again, to event 1 the EA does not react at all.

And if we use a fake Expert Advisor, we will have a good time sleeping.

 

The idea is clear. but it won't work. it would be akin to missing a single event.

But I've just tested a simple algorithm like this.

int rest=0;
int all=0;
bool click=false;
//------------------------------------------------------------------    OnInit
int OnInit() { EventChartCustom(0, 0, 0, 0, ""); return(0); }
//------------------------------------------------------------------    OnChartEvent
void OnChartEvent(const int id, const long& lparam, const double& dparam, const string& sparam)
{
        if (id==CHARTEVENT_OBJECT_CLICK) click=!click;
        if (!click) { EventChartCustom(0, 0, 0, 0, ""); all++; }
        else rest++;
        
        string txt="all="+string(all)+"  rest="+string(rest);
        SetButton(0, "btn", 0, txt, clrWhite, clrDarkBlue, 150, 150, 200, 50, 0, 9, "Tahoma", click);
        ChartRedraw(0);
}
//------------------------------------------------------------------ SetButton
void SetButton(long achart, string name, int wnd, string text, color txtclr, color bgclr, int x, int y, int dx, int dy, int corn=0, int fontsize=8, string font="Tahoma", bool state=false)
{
        ObjectCreate(achart, name, OBJ_BUTTON, wnd, 0, 0); ObjectSetInteger(achart, name, OBJPROP_CORNER, corn); 
        ObjectSetString(achart, name, OBJPROP_TEXT, text); ObjectSetInteger(achart, name, OBJPROP_STATE, state);
        ObjectSetInteger(achart, name, OBJPROP_COLOR, txtclr); ObjectSetInteger(achart, name, OBJPROP_BGCOLOR, bgclr); ObjectSetInteger(achart, name, OBJPROP_BORDER_COLOR, clrNONE);
        ObjectSetInteger(achart, name, OBJPROP_FONTSIZE, fontsize); ObjectSetString(achart, name, OBJPROP_FONT, font);
        ObjectSetInteger(achart, name, OBJPROP_XDISTANCE, x); ObjectSetInteger(achart, name, OBJPROP_YDISTANCE, y);
        ObjectSetInteger(achart, name, OBJPROP_XSIZE, dx); ObjectSetInteger(achart, name, OBJPROP_YSIZE, dy);
        ObjectSetInteger(achart, name, OBJPROP_SELECTABLE, false);
        ObjectSetInteger(achart, name, OBJPROP_BORDER_TYPE, 0);
        ObjectSetString(achart, name, OBJPROP_TOOLTIP, text);
}

All the events work as they should. There are no lags.

But if you put two times (or more) EventChartCustom in a line,

if (!click) { EventChartCustom(0, 0, 0, 0, ""); EventChartCustom(0, 0, 0, 0, ""); all++; }

there will be twice the lag.

Hence I conclude that everything works as it should, it is my code that has double EventChartCustom call somewhere, and this event is accumulated.

I will look in the code. For now, the topic can be closed.

 
sergeev:

The idea is clear. but it won't work. it would be akin to missing one event.

No. Yes, I meant that the charts are different for event 1 and 2

(1) I suspect it would work much slower for different threads.

(2) you can sleep if the advisor.

Well and 2 times (at least) slower.

 
свой OnCustomTimer в миллисекундах


#define MSECTIMER 100
#define TIMEREVENT 111
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- create timer
   EventSetTimer(60);
   EventSetCustomTimer(MSECTIMER);
//---
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- destroy timer
   EventKillTimer();

  }
//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
//---

  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void EventSetCustomTimer(int msec) 
  {
   EventChartCustom(0,TIMEREVENT,msec,NULL,NULL);
  }
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//---
   static uint lasttick=0;
   if(id==CHARTEVENT_CLICK) 
     {
      Print("Click");
     }

   if(id==CHARTEVENT_CUSTOM+TIMEREVENT) 
     {
      uint current=GetTickCount();
      if(lasttick+lparam<=current) 
        {
         lasttick=current;
         OnCustomTimer();
        }
     }
   EventSetCustomTimer(MSECTIMER);
  }
//+------------------------------------------------------------------+


void OnCustomTimer() 
  {
//
  }
//+------------------------------------------------------------------+
looked at the previous code - yes
and OnChartEvent could use a piggyback, which defaults to
EventSetCustomTimer
 
TheXpert:

No. Yes, I meant that the charts are different for event 1 and 2

(1) There is a suspicion that it would work much slower for different threads.

(2) You can sleep if the EA.

Well and 2 times (at least) slower.


It is true what they say - wiser in the morning. :) I have solved the problem. It even worked out very elegantly.

- Let's introduce counter of sent messages event_idle

- When sending the event, send this counter to LPARAM EventChartCustom(chart, VM_IDLE, event_idle, 0, "");

- and then in the OnChartEvent handler, rake out all VM_IDLE messages until the incoming LPARAM parameter is equal to the current event_idle.

like this

ulong event_idle=0; bool bidle;
void OnChartEvent(int iview, int id, long lparam, double dparam, string sparam)
{
    if (id==CHARTEVENT_CUSTOM+VM_IDLE)
    {
        if (event_idle>(ulong)lparam || bidle) { bidle=event_idle>(ulong)lparam; if (bidle) return; event_idle=0; } // если последнее посланное больше чем пришедшее, то сразу выходим
        event_idle++;
        ChartRedraw(m_chart); // обновили чарт
        EventChartCustom(m_chart, VM_IDLE, (long)event_idle, 0, ""); // отправили событие с указанием последнего счетчика
        return; 
    }
    EventChartCustom(m_chart, VM_IDLE, (long)event_idle, 0, ""); // отправили событие  с указанием последнего счетчика

    /*
        обработка остальных событий
    */
}

In this way, there will never be an overshoot on this event, as they will all be scraped.

Now the speed is fine without the event_idle queue enumeration :)

 
sergeev:

...But a second problem has emerged in that the message queue is failing to clear. overflows.

I can't find an answer to the question: how does event queue overflow affect RAM size? If the event queue turned out to be overflowing, where do the events that overflowed go? Is part of the memory, reserved for those events that happened to be "out of history", freed up?

Maybe my questions are not terminologically correct, but (I hope) they capture the essence of the problem.

 
Yedelkin:

I can't find an answer to the question: how does an event queue overflow affect RAM size? If the event queue appears to be overflowing, where do the events that overflowed the queue go?

That's the point: they don't. They accumulate.
 
sergeev:
that's the point: they don't go anywhere.

That is, if the event queue becomes full, then the events that overflowed the queue "eat up" the RAM, gradually increasing the size of the consumed RAM? But this is wrong. It seems that the events that "blew past the queue" should finally free the memory allocated for them.

... One year later I still haven't managed to get a coherent answer to my question about the size of the event queue. Thus, it's still not clear what frequency user events should be sent out so that they don't overflow the queue of terminal events...

Документация по MQL5: Стандартные константы, перечисления и структуры / Константы графиков / Типы событий графика
Документация по MQL5: Стандартные константы, перечисления и структуры / Константы графиков / Типы событий графика
  • www.mql5.com
Стандартные константы, перечисления и структуры / Константы графиков / Типы событий графика - Документация по MQL5
Reason: