Flux d'événements. Comment contrôler et rendre l'événement inactif ? (+ résolu)

 

Il y a un problème - j'ai besoin d'une fonction de mise à jour, mais plus rapide que MQL sur le timer - moins d'une seconde.
Solution - envoi de l'événement à moi-même - EventChartCustom dans OnChartEvent.

Tout fonctionne très rapidement. Mais le second problème est que la file de messages n'a pas le temps d'être nettoyée.

Par exemple, lorsque vous cliquez sur l'objet, l'événement CHARTEVENT_OBJECT_CLICK ne survient pas immédiatement, mais seulement après que tous les événements précédents ont été retirés de la file d'attente.
Et comme vous le comprenez, la file d'attente des événements est encombrée de EventChartCustom.

Fondamentalement, nous devons réaliser une mise à jour étroitement contrôlée d'une certaine fonction, mais en même temps

- il n'y avait pas de boucle sans fin comme while (true)
- mais aussi que OnChartEvent répond dès que l'événement graphique se produit.

Que faire dans cette situation ? Peut-être y a-t-il une autre option avec le contrôle d'envoi d'EventChartCustom ?

En d'autres termes, comment faire pour que MQL appelle une fonction plus d'une seconde, mais sans aucune file d'attente.

----------

La solution la plus simple (mais qui nécessite l'intervention d'un développeur) consiste à autoriser la réception de l'événement suivant dans la file d'attente des événements, mais sans quitter la fonction OnChartEvent.

C'est-à-dire que je veux que tous les événements vides de mon EventChartCustom soient nettoyés en une seule fois. Et n'autorisez pas le chargement de la file d'attente avec les événements restants.

 

Si vous n'envoyez un événement que lors du traitement de OnChartEvent, la file d'attente ne devrait logiquement pas déborder. Vous n'organisez pas cet événement partout, n'est-ce pas ?

Vous pouvez également envoyer l'événement par le biais du routage des événements. C'est-à-dire qu'il y a un indicateur ou autre Expert Advisor, qui est seulement nécessaire pour envoyer des réponses à certains événements à l'expéditeur.

 
TheXpert:

Si vous n'envoyez un événement que lors du traitement de OnChartEvent, la file d'attente ne devrait logiquement pas déborder.

Non, ça se déborde tout seul. EventChartCustom est appelé à OnChartEvent. Et il y a un flux dense d'événements. D'un côté, c'est ce dont vous avez besoin, mais d'un autre côté, il faut beaucoup de temps pour que les événements du tableau passent.

Vous pouvez également envoyer l'événement par le biais du pavé d'événements. C'est-à-dire qu'il existe un induke, ou autre Expert Advisor, qui n'est nécessaire que pour envoyer des réponses à certains événements à l'expéditeur.

J'y ai pensé de cette façon, mais je n'ai rien trouvé. Décrivez le schéma d'échange ?
 
sergeev:
J'y ai pensé, mais je n'ai rien trouvé. Veuillez décrire le système d'échange.

Nous disposons d'un indicateur (fil différent, il est peut-être meilleur). Il attrape l'événement 1. Dans ce cas, il est souhaitable de transmettre toutes les informations nécessaires pour être renvoyé.

La Turquie envoie l'événement 2 à l'expéditeur de l'événement 1.

L'EA capte l'événement 2 et renvoie l'événement 1. L'EA ne réagit pas du tout à l'événement 1.

Et si nous utilisons un faux conseiller expert, nous pourrons dormir.

 

L'idée est claire. mais cela ne fonctionnera pas. cela reviendrait à manquer un seul événement.

Mais je viens de tester un algorithme simple comme celui-ci.

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

Tous les événements fonctionnent comme ils le devraient. Il n'y a pas de décalage.

Mais si vous mettez deux fois (ou plus) EventChartCustom dans une ligne,

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

il y aura deux fois plus de décalage.

J'en conclus donc que tout fonctionne comme il se doit, c'est mon code qui a un double appel EventChartCustom quelque part, et cet événement est accumulé.

Je vais regarder dans le code. Pour l'instant, le sujet peut être clos.

 
sergeev:

L'idée est claire. mais cela ne fonctionnera pas. cela reviendrait à manquer un événement.

Non. Oui, je voulais dire que les graphiques sont différents pour les événements 1 et 2.

(1) Je pense que cela fonctionnerait beaucoup plus lentement pour des fils différents.

(2) vous pouvez dormir si le conseiller.

Bien et 2 fois (au moins) plus lent.

 
свой 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() 
  {
//
  }
//+------------------------------------------------------------------+
j'ai regardé le code précédent - oui
et OnChartEvent pourraient utiliser un piggyback, qui par défaut est
EventSetCustomTimer
 
TheXpert:

Non. Oui, je voulais dire que les graphiques sont différents pour les événements 1 et 2.

(1) Il y a un soupçon que cela fonctionnerait beaucoup plus lentement pour différents fils.

(2) Vous pouvez dormir si l'EA.

Bien et 2 fois (au moins) plus lent.


C'est vrai ce qu'on dit - plus sage le matin. :) J'ai résolu le problème. Cela a même fonctionné de manière très élégante.

- Introduisons le compteur de messages envoyés event_idle

- Lors de l'envoi de l'événement, envoyez ce compteur à LPARAM EventChartCustom(chart, VM_IDLE, event_idle, 0, "") ;

- et ensuite dans le gestionnaire OnChartEvent, ratisser tous les messages VM_IDLE jusqu'à ce que le paramètre LPARAM entrant soit égal à l'event_idle actuel.

comme ceci

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

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

De cette façon, il n'y aura jamais de dépassement sur cet événement, car ils seront tous éliminés.

Maintenant la vitesse est bonne sans l'énumération de la file d'attente event_idle :)

 
sergeev:

...Mais un deuxième problème est apparu : la file d'attente des messages ne se vide pas. Elle déborde.

Je ne trouve pas de réponse à la question suivante : comment le dépassement de la file d'attente des événements affecte-t-il la taille de la RAM ? Si la file d'attente des événements s'est avérée débordante, où vont les événements qui ont débordé ? Une partie de la mémoire, réservée aux événements qui se sont trouvés "hors de l'histoire", est-elle libérée ?

Mes questions ne sont peut-être pas terminologiquement correctes, mais (j'espère) elles saisissent l'essence du problème.

 
Yedelkin:

Je ne trouve pas de réponse à la question suivante : comment le dépassement de la file d'attente des événements affecte-t-il la taille de la RAM ? Si la file d'attente des événements semble déborder, où vont les événements qui ont débordé de la file d'attente ?

Justement, ils ne le font pas. Ils s'accumulent.
 
sergeev:
c'est le but : ils ne vont nulle part.

C'est-à-dire que si la file d'attente des événements est pleine, les événements qui ont débordé de la file d'attente "mangent" la RAM, augmentant progressivement la taille de la RAM consommée ? Mais c'est faux. Il semble que les événements qui ont "dépassé la file d'attente" devraient enfin libérer la mémoire qui leur était réservée.

... Un an plus tard, je n'ai toujours pas réussi à obtenir une réponse cohérente à la question de la taille de la file d'attente des événements. Ainsi, on ne sait toujours pas à quelle fréquence les événements utilisateurs doivent être envoyés pour qu'ils ne débordent pas de la file d'attente des événements terminaux...

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