Event-Stream. Wie kann man das Ereignis kontrollieren und in den Leerlauf versetzen? (+ gelöst)

 

Es gibt ein Problem - ich brauche, um einige Funktion zu aktualisieren, aber schneller als MQL auf Timer - weniger als 1 Sekunde.
Lösung - machte Ereignis senden an mich selbst - EventChartCustom in OnChartEvent.

Alles funktioniert sehr schnell. Das zweite Problem ist, dass die Nachrichtenwarteschlange keine Zeit hat, bereinigt zu werden.

Wenn Sie zum Beispiel auf das Objekt klicken, wird das Ereignis CHARTEVENT_OBJECT_CLICK nicht sofort ausgelöst, sondern erst, nachdem alle vorherigen Ereignisse aus der Warteschlange entfernt worden sind.
Und wie Sie verstehen, ist die Ereignis-Warteschlange mit EventChartCustom verstopft .

Im Grunde müssen wir eine streng kontrollierte Aktualisierung einer Funktion erreichen, aber gleichzeitig

- es gab keine Endlosschleife wie while (true)
- sondern auch, dass OnChartEvent reagiert, sobald das Diagrammereignis eintritt.

Was ist in dieser Situation zu tun? Vielleicht gibt es eine andere Option mit EventChartCustom Senden Kontrolle ?

Mit anderen Worten - wie kann man MQL dazu bringen, eine Funktion länger als 1 Sekunde aufzurufen, aber ohne Warteschlangen.

----------

Die einfachste Lösung (aber mit Beteiligung des Entwicklers) besteht darin, den Empfang des nächsten Ereignisses aus der Ereigniswarteschlange zuzulassen, ohne jedoch die Funktion OnChartEvent zu beenden.

D.h., ich möchte alle leeren Ereignisse aus meinem EventChartCustom in einem Rutsch bereinigt werden. Und erlauben Sie nicht, die Warteschlange mit linken Ereignissen zu beladen.

 

Wenn Sie nur bei der Behandlung von OnChartEvent ein Ereignis senden, sollte die Warteschlange logischerweise nicht überlaufen. Sie bieten diese Veranstaltung nicht überall an, oder?

Sie können das Ereignis auch über das Ereignis-Routing senden. D.h. es gibt einen Indikator oder einen anderen Expert Advisor, der nur benötigt wird, um Antwort-Ereignisse auf bestimmte Ereignisse an den Absender zu senden.

 
TheXpert:

Wenn Sie nur ein Ereignis senden, wenn OnChartEvent verarbeitet wird, sollte die Warteschlange logischerweise nicht überlaufen.

Nein, er läuft einfach über. EventChartCustom wird bei OnChartEvent aufgerufen . Und es gibt einen dichten Strom von Ereignissen. Einerseits ist das genau das, was Sie brauchen, andererseits dauert es sehr lange, bis die Kartenereignisse durch sind.

Sie können das Ereignis auch über das Ereignis-Pad senden. D.h., es gibt einen Induke oder einen anderen Expert Advisor, der nur benötigt wird, um Antwort-Ereignisse auf bestimmte Ereignisse an den Absender zu senden.

Ich habe darüber nachgedacht, bin aber nicht fündig geworden. Beschreiben Sie das Umtauschverfahren?
 
sergeev:
Ich habe darüber nachgedacht, aber mir ist nichts eingefallen. Bitte beschreiben Sie das Austauschprogramm.

Wir haben einen Indikator (verschiedene Threads, es kann besser sein). Sie fängt das Ereignis 1 ab. In diesem Fall ist es wünschenswert, alle notwendigen Informationen zu übermitteln, die zurückgeschickt werden sollen.

Die Türkei sendet Ereignis 2 an den Absender von Ereignis 1.

Der EA fängt das Ereignis 2 ab und sendet erneut das Ereignis 1, auf das Ereignis 1 reagiert der EA überhaupt nicht.

Und wenn wir einen gefälschten Expert Advisor verwenden, werden wir schlafen können.

 

Die Idee ist klar, aber es wird nicht funktionieren. Es wäre so, als würde man ein einziges Ereignis verpassen.

Aber ich habe gerade einen einfachen Algorithmus wie diesen getestet.

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

Alle Ereignisse funktionieren so, wie sie sollten. Es gibt keine Verzögerungen.

Aber wenn Sie zwei (oder mehr) EventChartCustom in eine Zeile setzen,

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

wird die Verzögerung doppelt so groß sein.

Daraus schließe ich, dass alles funktioniert, wie es sollte, es ist mein Code, der doppelte EventChartCustom Aufruf irgendwo hat, und dieses Ereignis wird akkumuliert.

Ich werde im Code nachsehen. Das Thema kann vorerst geschlossen werden.

 
sergeev:

Die Idee ist klar, aber es wird nicht funktionieren. Es wäre so, als würde man ein Ereignis verpassen.

Nein. Ja, ich meinte, dass die Diagramme für Ereignis 1 und 2 unterschiedlich sind.

(1) Ich vermute, dass es bei verschiedenen Threads viel langsamer funktionieren würde.

(2) Sie können schlafen, wenn der Berater.

Nun, und 2 Mal (mindestens) langsamer.

 
свой 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() 
  {
//
  }
//+------------------------------------------------------------------+
Ich habe mir den vorherigen Code angesehen - ja,
und OnChartEvent könnten ein Huckepack-Ereignis verwenden, das standardmäßig auf
EventSetCustomTimer
 
TheXpert:

Nein. Ja, ich meinte, dass die Diagramme für Ereignis 1 und 2 unterschiedlich sind.

(1) Es besteht der Verdacht, dass es bei verschiedenen Threads viel langsamer arbeiten würde.

(2) Sie können schlafen, wenn der EA.

Nun, und 2 Mal (mindestens) langsamer.


Es stimmt, was man sagt: Morgenstund hat Gold im Mund. :) Ich habe das Problem gelöst. Es hat sogar sehr elegant funktioniert.

- Führen wir den Zähler der gesendeten Nachrichten ein event_idle

- Beim Senden des Ereignisses wird dieser Zähler an LPARAM EventChartCustom(chart, VM_IDLE, event_idle, 0, "") gesendet;

- und dann im OnChartEvent-Handler alle VM_IDLE-Nachrichten ausgeben, bis der eingehende LPARAM-Parameter gleich dem aktuellen event_idle ist.

wie diese

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, ""); // отправили событие  с указанием последнего счетчика

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

Auf diese Weise wird es bei diesem Ereignis nie zu einer Überschreitung kommen, da sie alle verschrottet werden.

Jetzt ist die Geschwindigkeit auch ohne die event_idle queue enumeration gut :)

 
sergeev:

...Aber ein zweites Problem ist aufgetaucht: Die Nachrichtenwarteschlange wird nicht geleert, sie läuft über.

Ich kann keine Antwort auf die Frage finden: Wie wirkt sich ein Überlauf der Ereigniswarteschlange auf die Größe des Arbeitsspeichers aus? Wenn sich herausstellt, dass die Ereigniswarteschlange überläuft, wohin gehen dann die übergelaufenen Ereignisse? Wird ein Teil des Gedächtnisses, der für die Ereignisse reserviert ist, die "aus der Geschichte herausgefallen" sind, wieder freigegeben?

Vielleicht sind meine Fragen terminologisch nicht korrekt, aber sie treffen (so hoffe ich) den Kern des Problems.

 
Yedelkin:

Ich kann keine Antwort auf die Frage finden: Wie wirkt sich ein Überlauf der Ereigniswarteschlange auf die RAM-Größe aus? Wenn die Ereigniswarteschlange scheinbar überläuft, wohin gehen dann die Ereignisse, die die Warteschlange überlaufen haben?

Das ist der Punkt: Sie tun es nicht. Sie sammeln sich an.
 
sergeev:
Das ist der Punkt: Sie führen nirgendwohin.

Das heißt, wenn die Ereignis-Warteschlange voll wird, dann "fressen" die Ereignisse, die die Warteschlange überlaufen haben, den Arbeitsspeicher auf, wodurch der verbrauchte Arbeitsspeicher allmählich größer wird? Doch das ist falsch. Es scheint, dass die Ereignisse, die "an der Warteschlange vorbeigelaufen" sind, endlich den für sie reservierten Speicher freigeben sollten.

... Ein Jahr später habe ich immer noch keine schlüssige Antwort auf meine Frage nach der Größe der Ereignis-Warteschlange erhalten. Es ist also immer noch nicht klar, wie oft Benutzerereignisse gesendet werden sollten, damit sie die Warteschlange der Terminalereignisse nicht überfüllen...

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