Flujo de eventos. ¿Cómo controlar y hacer que el evento sea inactivo? (+ resuelto) - página 6

 
sergeev:

¿Y ya has hecho una nueva pregunta?

No es apropiado que un moderador inicie una inundación. Para aclarar. Cuando un usuario (incluido un moderador) añade un nuevo mensaje a un hilo, es habitual llamarlo "respuesta". Aunque sea una réplica de carácter sarcástico.

Por lo tanto, una vez más, con una aclaración: si lo consideras un circo, siéntete libre de borrarlo, o intenta hacer un nuevo mensaje al respecto. Por otra parte, la información inexacta puede inducir a error a los usuarios.

Para añadir. Seré el primero en agradecerte si resulta oficialmente (si ayudas a averiguarlo) que los eventos de los usuarios llenan la cola según las antiguas reglas.

 
Yedelkin:

Yo añadiré. Seré el primero en agradecerte si resulta oficialmente (si ayudas a averiguarlo) que los eventos personalizados llenan la cola según las antiguas reglas.

A grandes rasgos, el manejo de los eventos nunca cambió. Lo que ocurre es que la ayuda no se ha redactado inicialmente de forma correcta.
 
Rosh:
A grandes rasgos, el manejo de los eventos nunca ha cambiado. Es que originalmente no estaba escrito correctamente en la ayuda.
Gracias. Es una pena. Así que las viejas reglas del manual son erróneas. Perdón por la frivolidad.
 
sergeev:

...

El problema no parece volver a surgir, como si nunca hubiera ocurrido.Alex, ¿podrías echar un vistazo en tu oficina, si tienes un minuto libre? Es decir, cómo funcionará ahora con y sin su complemento.
 

Utilizo activamente el mensaje de inactividad creado en cada una de mis aplicaciones. Todo funciona.

 
sergeev:

Utilizo activamente el mensaje de inactividad creado en cada una de mis aplicaciones. Todo está funcionando.

Es posible que ya no tenga el problema porque ahora estoy probando 3 caracteres en lugar de 12 como antes. Escribiré si encuentro una dependencia. Gracias.
 

sergeev: 

He cogido un bicho.

Sucede debido al envío del evento EventChartCustom del Asesor Experto a sí mismo. Resulta que este envío de evento provoca la actualización del gráfico (ChartRedraw) de la ventana principal.

//---

Hice tal experto para probar su solución y al mismo tiempo trató de resolver el problema con el parpadeo super frecuente de texto durante la edición de un objeto OBJ_EDIT.

//---

//+------------------------------------------------------------------+
//|                                                 OnChartEvent.mq5 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.00"
//---
long chart_id=0;
string OnOff_event_idle="On/Off event_idle++";
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   chart_id=ChartID();
//---
   if(!GlobalVariableCheck(OnOff_event_idle)) { GlobalVariableSet(OnOff_event_idle,1); }
//---
   Create_Edit(chart_id,0,"Edit_Area","HELLO",CORNER_LEFT_UPPER,"Arial",7,clrWhite,38,18,95,4,1,clrBlack);
   Create_Button(chart_id,0,"Start_event_idle","START event_idle++",ANCHOR_RIGHT_UPPER,CORNER_LEFT_UPPER,"Arial",8,clrWhite,clrFireBrick,clrNONE,130,26,4,28,1);
//---
   Comment("id: ",0,"\n",
           "event_idle++: ",event_idle
           );
//---
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   Comment("");
   ObjectsDeleteAll(chart_id,-1,-1);
  }
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
bool bidle=false;
ushort VM_IDLE=500;
ulong event_idle=0; // счётчик событий
//---
void OnChartEvent(const int     id,
                  const long   &lparam,
                  const double &dparam,
                  const string &sparam)
  {
   if(GlobalVariableGet(OnOff_event_idle)==1)
     {
      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++; // увеличили счётчик событий
         //---
         Comment("id: ",id,"\n",
                 "event_idle++: ",event_idle
                 );
         //---
         EventChartCustom(chart_id,VM_IDLE,(long)event_idle,0,""); return; // отправили событие с указанием последнего счетчика
        }
      //---
      EventChartCustom(chart_id,VM_IDLE,(long)event_idle,0,""); // отправили событие с указанием последнего счетчика
     }
//+------------------------------------------------------------------+
//| СОБЫТИЕ_CHARTEVENT_CLICK                                         |
//+------------------------------------------------------------------+
   if(id==CHARTEVENT_CLICK)
     {
      Print("Reset. Event_idle: ",event_idle);
      //---
      event_idle=0;
      //---
      Comment("id: ",id,"\n",
              "event_idle++: ",event_idle
              );
     }
//+------------------------------------------------------------------+
//| СОБЫТИЕ_CHARTEVENT_OBJECT_CLICK                                  |
//+------------------------------------------------------------------+
   if(id==CHARTEVENT_OBJECT_CLICK)
     {
      if(sparam=="Edit_Area")
        {
         if((int)GlobalVariableGet(OnOff_event_idle)==0) { GlobalVariableSet(OnOff_event_idle,1); }
         if((int)GlobalVariableGet(OnOff_event_idle)==1) { GlobalVariableSet(OnOff_event_idle,0); }
        }
      //---
      if(sparam=="Start_event_idle")
        {
         if((int)GlobalVariableGet(OnOff_event_idle)==0) { GlobalVariableSet(OnOff_event_idle,1); ChartRedraw(); return; }
         if((int)GlobalVariableGet(OnOff_event_idle)==1) { GlobalVariableSet(OnOff_event_idle,0); ChartRedraw(); return; }
        }
     }
//+------------------------------------------------------------------+
//| CHARTEVENT_OBJECTS_ENDEDIT                                       |
//+------------------------------------------------------------------+
   if(id==CHARTEVENT_OBJECT_ENDEDIT)
     {
      if(ObjectGetInteger(chart_id,"Start_event_idle",OBJPROP_STATE)) { GlobalVariableSet(OnOff_event_idle,1); }
     }
  }
//+------------------------------------------------------------------+
//| СОЗДАНИЕ_ОБЪЕКТА_BUTTON                                          |
//+------------------------------------------------------------------+
void Create_Button(long   chrt_id,   // id графика
                   int    nmb_win,   // номер окна
                   string lable_nm,  // имя объекта
                   string rename,    // отображаемое имя
                   long   anchor,    // точка привязки
                   long   corner,    // угол привязки
                   string font_bsc,  // шрифт
                   int    font_size, // размер шрифта
                   color  font_clr,  // цвет шрифта
                   color  bg_color,  // цвет фона
                   color  brd_color, // цвет рамки
                   int    xsize,     // ширина
                   int    ysize,     // высота
                   int    x_dist,    // координата по шкале X
                   int    y_dist,    // координата по шкале Y
                   long   zorder)    // приоритет
  {
   if(ObjectCreate(chrt_id,lable_nm,OBJ_BUTTON,nmb_win,0,0)) // создание объекта
     {
      ObjectSetString(chrt_id,lable_nm,OBJPROP_TEXT,rename);             // установка имени
      ObjectSetString(chrt_id,lable_nm,OBJPROP_FONT,font_bsc);           // установка шрифта
      ObjectSetInteger(chrt_id,lable_nm,OBJPROP_COLOR,font_clr);         // установка цвета шрифта
      ObjectSetInteger(chrt_id,lable_nm,OBJPROP_BGCOLOR,bg_color);       // установка цвета фона
      ObjectSetInteger(chrt_id,lable_nm,OBJPROP_BORDER_COLOR,brd_color); // установка цвета фона
      ObjectSetInteger(chrt_id,lable_nm,OBJPROP_ANCHOR,anchor);          // установка точки привязки
      ObjectSetInteger(chrt_id,lable_nm,OBJPROP_CORNER,corner);          // установка угола привязки
      ObjectSetInteger(chrt_id,lable_nm,OBJPROP_FONTSIZE,font_size);     // установка размера шрифта
      ObjectSetInteger(chrt_id,lable_nm,OBJPROP_XSIZE,xsize);            // установка ширины X
      ObjectSetInteger(chrt_id,lable_nm,OBJPROP_YSIZE,ysize);            // установка высоты Y
      ObjectSetInteger(chrt_id,lable_nm,OBJPROP_XDISTANCE,x_dist);       // установка координаты X
      ObjectSetInteger(chrt_id,lable_nm,OBJPROP_YDISTANCE,y_dist);       // установка координаты Y
      ObjectSetInteger(chrt_id,lable_nm,OBJPROP_SELECTABLE,false);       // нельзя выделить объект, если FALSE
      ObjectSetInteger(chart_id,lable_nm,OBJPROP_ZORDER,zorder);         // Приоритет выше/ниже
      ObjectSetString(chrt_id,lable_nm,OBJPROP_TOOLTIP,"\n");            // нет всплывающей подсказки, если "\n"
     }
  }
//+------------------------------------------------------------------+
//| СОЗДАНИЕ_ОБЪЕКТА_EDIT                                            |
//+------------------------------------------------------------------+
void Create_Edit(long   chrt_id,   // id графика
                 int    nmb_win,   // номер окна (подокна)
                 string lable_nm,  // имя объекта
                 string text,      // отображаемый текст
                 long   corner,    // угол привязки
                 string font_bsc,  // шрифт
                 int    font_size, // размер шрифта
                 color  font_clr,  // цвет шрифта
                 int    xsize,     // ширина
                 int    ysize,     // высота
                 int    x_dist,    // координата по шкале X
                 int    y_dist,    // координата по шкале Y
                 long   zorder,    // приоритет
                 color  clr)       // цвет фона
  {
   if(ObjectCreate(chrt_id,lable_nm,OBJ_EDIT,nmb_win,0,0)) // создание объекта
     {
      ObjectSetString(chrt_id,lable_nm,OBJPROP_TEXT,text);            // установка имени
      ObjectSetInteger(chrt_id,lable_nm,OBJPROP_CORNER,corner);       // установка угла привязки
      ObjectSetString(chrt_id,lable_nm,OBJPROP_FONT,font_bsc);        // установка шрифта
      ObjectSetInteger(chrt_id,lable_nm,OBJPROP_FONTSIZE,font_size);  // установка размера шрифта
      ObjectSetInteger(chart_id,lable_nm,OBJPROP_COLOR,font_clr);     // цвет шрифта
      ObjectSetInteger(chart_id,lable_nm,OBJPROP_BGCOLOR,clr);        // цвет фона
      ObjectSetInteger(chart_id,lable_nm,OBJPROP_XSIZE,xsize);        // ширина
      ObjectSetInteger(chart_id,lable_nm,OBJPROP_YSIZE,ysize);        // высота
      ObjectSetInteger(chrt_id,lable_nm,OBJPROP_XDISTANCE,x_dist);    // установка координаты X
      ObjectSetInteger(chrt_id,lable_nm,OBJPROP_YDISTANCE,y_dist);    // установка координаты Y
      ObjectSetInteger(chrt_id,lable_nm,OBJPROP_SELECTABLE,false);    // нельзя выделить объект, если FALSE
      ObjectSetInteger(chart_id,lable_nm,OBJPROP_ZORDER,zorder);      // Приоритет выше/ниже
      ObjectSetString(chrt_id,lable_nm,OBJPROP_TOOLTIP,"\n");         // нет всплывающей подсказки, если "\n"
     }
  }
//+------------------------------------------------------------------+

//---

Después de lanzar el Asesor Experto, verá lo siguiente en el gráfico en la esquina superior izquierda:

//---

Al hacer clic en el botón"START event_idle++" accederá a su solución(Alex). Vemos que el contador event_idle++ se incrementa justo en el gráfico.

Mientras el botón esté pulsado, tu código funcionará. Pero consume muchos recursos. La carga de la CPU (probada en doble núcleo) oscila entre el ~90% y el ~100%. La carga de la CPU oscila entre el ~5% y el ~10% antes del arranque o cuando se suelta el botón. Al hacer clic (con el botón izquierdo) en el gráfico, el contador se pone a cero.

La introducción de texto en el campo de entrada no causa parpadeo, porque en el momento de la entrada su código está desactivado por la variable global"On/Off event_idle++". Es una muleta, por supuesto, pero como solución temporal está bien para algunas soluciones simples.

La carga de la CPU no es el único problema. Cuando el contador está en marcha, las ventanas del terminal de operaciones se abren rápidamente, pero el cambio de tamaño de las ventanas se ralentiza bastante. No siempre, pero esos momentos existen.


Archivos adjuntos:
 
tol64:

La carga de la CPU no es el único problema. Cuando el contador está en marcha, las ventanas del terminal de operaciones se abren rápidamente, pero el cambio de tamaño de las ventanas se ralentiza bastante. No siempre, pero hay momentos así.

El problema de la carga de la CPU puede resolverse como sigue. Especifica que el contador de eventos se actualiza una vez por segundo. Añadimos el siguiente código:

En OnInit():

EventSetTimer(1);

//---

En el cuerpo del programa:

//+------------------------------------------------------------------+
//| ТАЙМЕР                                                           |
//+------------------------------------------------------------------+
long countSecond=0;
//---
void OnTimer()
  {
   if(GlobalVariableGet(OnOff_event_idle)==1)
     {
      countSecond++;
     }
  }

//---

Al código de Alex(marcado en rojo):

   if(GlobalVariableGet(OnOff_event_idle)==1)
     {
      if(id==CHARTEVENT_CUSTOM+VM_IDLE && countSecond>0)
        {
         // Если последнее посланное больше, чем пришедшее, то сразу выходим
         if(event_idle>(ulong)lparam || bidle)
           {
            bidle=event_idle>(ulong)lparam;
            //---
            if(bidle) { return; }
            //---
            event_idle=0;
           }
         //---
         event_idle++; // увеличили счётчик событий
         //---
         Comment("id: ",id,"\n",
                 "event_idle++: ",event_idle
                 );
         //---
         // Отправили событие с указанием последнего счетчика
         EventChartCustom(chart_id,VM_IDLE,(long)event_idle,0,""); countSecond=0; return;
        }
      //---
      // Отправили событие с указанием последнего счетчика
      EventChartCustom(chart_id,VM_IDLE,(long)event_idle,0,""); countSecond=0;
     }

//---

En el bloque manejador de eventosCHARTEVENT_CLICK(marcado en rojo):

//+------------------------------------------------------------------+
//| СОБЫТИЕ_CHARTEVENT_CLICK                                         |
//+------------------------------------------------------------------+
   if(id==CHARTEVENT_CLICK)
     {
      Print("Reset. Event_idle: ",event_idle);
      //---
      event_idle=0;
      countSecond=0;
      //---
      Comment("id: ",id,"\n",
              "event_idle++: ",event_idle
              );
     }

//---

El bloque del manejador del evento CHARTEVENT_OBJECT_CLICK debe ser editado de la siguiente manera + El estado del botón debe ser revisado igualmente, porque a veces incluso presionándolo "erróneamente" lo dejará deprimido, si estaba así antes, pero el resto del código en el bloque funcionará y comenzará la confusión:

//+------------------------------------------------------------------+
//| СОБЫТИЕ_CHARTEVENT_OBJECT_CLICK                                  |
//+------------------------------------------------------------------+
   if(id==CHARTEVENT_OBJECT_CLICK)
     {
      if(sparam=="Edit_Area")
        {
         if((int)GlobalVariableGet(OnOff_event_idle)==0) { GlobalVariableSet(OnOff_event_idle,1); }
         if((int)GlobalVariableGet(OnOff_event_idle)==1) { GlobalVariableSet(OnOff_event_idle,0); }
        }
      //---
      if(sparam=="Start_event_idle")
        {
         if((int)GlobalVariableGet(OnOff_event_idle)==0)
           {
            countSecond=0;
            GlobalVariableSet(OnOff_event_idle,1);
            ObjectSetInteger(chart_id,"Start_event_idle",OBJPROP_STATE,true);
            //---
            ChartRedraw(); return;
           }
         //---
         if((int)GlobalVariableGet(OnOff_event_idle)==1)
           {
            countSecond=0;
            GlobalVariableSet(OnOff_event_idle,0);
            ObjectSetInteger(chart_id,"Start_event_idle",OBJPROP_STATE,false);
            //---
            ChartRedraw(); return;
           }
        }
     }

//---

Ahora se pone más interesante. :)

//---

P.D. Si tiene muchos segundos, puede intentar jugar con GetTickCount().

 

¿Qué puedo decir?

1. Es una carga para la CPU. Quítalo y se quedará quieto.

2. El bucle de inactividad en sí mismo no tiene un efecto notable en la CPU.

3. El problema del parpadeo del edith no es un problema con un solo gráfico 0. Es un problema con el envío de un evento al gráfico de objetos. Esto hace que el gráfico principal 0 se redibuje y dé parpadeos.

 
sergeev:

¿Qué puedo decir?

1. Es una carga para la CPU. Quítalo y se quedará tranquilo.

2. El bucle de inactividad en sí mismo no tiene un efecto notable en la CPU.

3. El problema del parpadeo del edith no es un problema de una sola carta 0. Es un problema de envío de un evento a la carta objeto. Esto hace que el gráfico principal 0 se redibuje y dé parpadeos.

Gracias por la aclaración. Lo investigaré.
Razón de la queja: