Flusso di eventi. Come controllare e rendere l'evento inattivo? (+ risolto)

 

C'è un problema - ho bisogno di fare l'aggiornamento di qualche funzione, ma più veloce di MQL su timer - meno di 1 secondo.
Soluzione - fatto l'invio dell'evento a me stesso - EventChartCustom in OnChartEvent.

Tutto funziona molto velocemente. Ma il secondo problema è che la coda dei messaggi non ha tempo per essere pulita.

Per esempio, quando si clicca sull'oggetto l'evento CHARTEVENT_OBJECT_CLICK non verrà subito, ma solo dopo che tutti gli eventi precedenti sono stati rimossi dalla coda.
E come avete capito la coda degli eventi è intasata da EventChartCustom.

Fondamentalmente, abbiamo bisogno di ottenere un aggiornamento strettamente controllato di qualche funzione, ma allo stesso tempo

- non c'era un ciclo infinito come while (true)
- ma anche che OnChartEvent risponde non appena si verifica l'evento grafico.

Cosa fare in questa situazione? Forse c'è un'altra opzione con il controllo di invio EventChartCustom?

In altre parole - come fare in modo che MQL chiami qualche funzione più di 1 secondo, ma senza alcuna coda.

----------

La soluzione più semplice (ma con il coinvolgimento dello sviluppatore) è quella di permettere la ricezione del prossimo evento dalla coda degli eventi, ma senza uscire dalla funzione OnChartEvent.

Cioè, voglio che tutti gli eventi vuoti del mio EventChartCustom siano puliti in una volta sola. E non permettere di caricare la coda con eventi lasciati.

 

Se si invia un evento solo quando si gestisce OnChartEvent, la coda non dovrebbe logicamente traboccare. Non gestite questo evento ovunque, vero?

Puoi anche inviare l'evento attraverso il routing degli eventi. Cioè c'è un indicatore o un altro Expert Advisor, che è necessario solo per inviare eventi di risposta a certi eventi al mittente.

 
TheXpert:

Se si invia un evento solo quando OnChartEvent viene elaborato, la coda non dovrebbe logicamente traboccare.

No, semplicemente trabocca da solo. EventChartCustom è chiamato a OnChartEvent. E c'è un denso flusso di eventi. Da un lato è quello che ti serve, ma dall'altro ci vuole molto tempo per gli eventi grafici.

Puoi anche inviare l'evento attraverso il pad degli eventi. Cioè, c'è un induke, o un altro Expert Advisor, che è necessario solo per inviare eventi di risposta a certi eventi al mittente.

Ci ho pensato in questo modo, ma non mi è venuto in mente niente. Descrivere lo schema di scambio?
 
sergeev:
Ci ho pensato, ma non ho trovato nulla. Si prega di descrivere lo schema di scambio.

Abbiamo un indicatore (fili diversi, può essere meglio). Cattura l'evento 1. Nel caso, è auspicabile passare tutte le informazioni necessarie per essere inviati indietro.

Turkey invia l'evento 2 al mittente dell'evento 1.

L'EA cattura l'evento 2 e invia nuovamente l'evento 1, all'evento 1 l'EA non reagisce affatto.

E se usiamo un falso Expert Advisor, ci divertiremo a dormire.

 

L'idea è chiara, ma non funzionerà, sarebbe come perdere un singolo evento.

Ma ho appena testato un semplice algoritmo come questo.

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);
}

Tutti gli eventi funzionano come dovrebbero. Non ci sono ritardi.

Ma se metti due volte (o più) EventChartCustom in una linea,

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

ci sarà il doppio del ritardo.

Quindi concludo che tutto funziona come dovrebbe, è il mio codice che ha una doppia chiamata EventChartCustom da qualche parte, e questo evento è accumulato.

Guarderò nel codice. Per ora, l'argomento può essere chiuso.

 
sergeev:

L'idea è chiara, ma non funzionerà, sarebbe come perdere un evento.

No. Sì, volevo dire che i grafici sono diversi per l'evento 1 e 2

(1) Ho il sospetto che funzionerebbe molto più lentamente per diversi thread.

(2) si può dormire se un consulente.

Bene e 2 volte (almeno) più lento.

 
свой 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() 
  {
//
  }
//+------------------------------------------------------------------+
ha guardato il codice precedente - sì
e OnChartEvent potrebbe usare un piggyback, che per default è
EventSetCustomTimer
 
TheXpert:

No. Sì, volevo dire che i grafici sono diversi per l'evento 1 e 2

(1) C'è il sospetto che funzionerebbe molto più lentamente per diversi thread.

(2) Si può dormire se l'EA.

Bene e 2 volte (almeno) più lento.


È vero quello che si dice: più saggi al mattino. :) Ho risolto il problema. Ha anche funzionato in modo molto elegante.

- Introduciamo il contatore dei messaggi inviati event_idle

- Quando si invia l'evento, si invia questo contatore a LPARAM EventChartCustom(chart, VM_IDLE, event_idle, 0, "");

- e poi nel gestore OnChartEvent, rastrellare tutti i messaggi VM_IDLE fino a quando il parametro LPARAM in arrivo è uguale all'event_idle corrente.

come questo

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 questo modo, non ci sarà mai un overshoot su questo evento, perché saranno tutti raschiati.

Ora la velocità va bene senza l'enumerazione della coda event_idle :)

 
sergeev:

...Ma è emerso un secondo problema: la coda dei messaggi non riesce a cancellarsi.

Non riesco a trovare una risposta alla domanda: come influisce l'overflow della coda degli eventi sulla dimensione della RAM? Se la coda degli eventi è risultata traboccante, dove vanno a finire gli eventi che sono traboccati? Si libera una parte della memoria, riservata a quegli eventi che erano "fuori dalla storia"?

Forse le mie domande non sono terminologicamente corrette, ma (spero) catturano l'essenza del problema.

 
Yedelkin:

Non riesco a trovare una risposta alla domanda: in che modo un overflow della coda degli eventi influisce sulla dimensione della RAM? Se la coda degli eventi sembra traboccare, dove vanno a finire gli eventi che hanno fatto traboccare la coda?

Questo è il punto: non lo fanno, si accumulano.
 
sergeev:
Questo è il punto: non vanno da nessuna parte.

Cioè, se la coda degli eventi si riempie, allora gli eventi che hanno fatto traboccare la coda "mangiano" la RAM, aumentando gradualmente la dimensione della RAM consumata? Ma questo è sbagliato. Sembra che gli eventi che "hanno superato la coda" dovrebbero finalmente liberare la memoria a loro riservata.

... Un anno dopo non sono ancora riuscito a ottenere una risposta coerente alla mia domanda sulla dimensione della coda degli eventi. Così, non è ancora chiaro con quale frequenza gli eventi utente dovrebbero essere inviati in modo che non trabocchino nella coda degli eventi del terminale...

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