Fluxo de eventos. Como controlar e tornar o evento inactivo ? (+ resolvido)

 

Há um problema - preciso de actualizar alguma função, mas mais rápido do que o MQL no temporizador - menos de 1 segundo.
Solução - envio de eventos feito a mim mesmo - EventChartCustom in OnChartEvent.

Tudo funciona muito rapidamente. Mas o segundo problema é que a fila de mensagens não tem tempo para ser limpa.

Por exemplo, ao clicar no objecto o evento CHARTEVENT_OBJECT_CLICK não virá de uma só vez, mas apenas depois de todos os eventos anteriores terem sido retirados da fila.
E, como se sabe, a fila de eventos está entupida com EventChartCustom.

Basicamente, necessitamos de conseguir uma actualização rigorosamente controlada de alguma função, mas ao mesmo tempo

- não havia um loop infinito como quando (verdade)
- mas também que a OnChartEvent responde assim que o evento gráfico acontece.

O que fazer nesta situação? Talvez haja outra opção com o controlo de envio de EventChartCustom?

Por outras palavras - como fazer a MQL chamar alguma função mais de 1 segundo, mas sem quaisquer filas de espera.

----------

A solução mais fácil (mas com a participação do desenvolvedor) é permitir receber o próximo evento da fila de eventos, mas sem sair da função OnChartEvent.

Isto é, quero que todos os eventos vazios do meu EventChartCustom sejam limpos de uma só vez. E não permitir carregar a fila com eventos à esquerda.

 

Se apenas enviar um evento quando manusear o OnChartEvent, a fila não deve, logicamente, transbordar. Não realiza este evento em todo o lado, pois não?

Também se pode enviar o evento através do encaminhamento do evento. Isto é, existe um indicador ou outro Expert Advisor, que só é necessário para enviar eventos de resposta a determinados eventos para o remetente.

 
TheXpert:

Se apenas enviar um evento ao manusear o OnChartEvent, a fila não deve, logicamente, transbordar.

Não, apenas transborda por si só. EventChartCustom é chamado na OnChartEvent . E há um fluxo denso de eventos. Por um lado é o que se precisa, mas, por outro lado, leva muito tempo para que os eventos do gráfico passem.

Também pode enviar o evento através do bloco de eventos. Ou seja, existe um induke, ou outro conselheiro, que só é necessário para enviar eventos de resposta a determinados eventos ao remetente.

Pensei nisso desta forma, mas não encontrei nada. Descrever o esquema de intercâmbio?
 
sergeev:
Pensei nisso, mas não encontrei nada. Por favor, descreva o esquema de intercâmbio.

Temos um indicador (fios diferentes, pode ser melhor). Apanha o evento 1. No caso, é desejável transmitir toda a informação necessária para ser enviada de volta.

A Turquia envia o evento 2 para o evento 1 remetente.

A EA captura o evento 2 e envia novamente o evento 1, para o evento 1 a EA não reage de todo.

E se usarmos um falso Conselheiro Especialista, poderemos dormir.

 

A ideia é clara. mas não vai funcionar. seria como se faltasse um único evento.

Mas eu acabei de testar um algoritmo simples como este.

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

Todos os eventos funcionam como deveriam. Não há desfasamentos.

Mas se colocar dois (ou mais) EventChartCustom numa linha,

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

haverá o dobro do atraso.

Assim, concluo que tudo funciona como deveria, é o meu código que tem o dobro EventChartCustom call algures, e este evento é acumulado.

Vou procurar no código. Por agora, o tema pode ser encerrado.

 
sergeev:

A ideia é clara. mas não vai funcionar. seria como se faltasse um evento.

Não. Sim, quis dizer que os gráficos são diferentes para os eventos 1 e 2

(1) Suspeito que funcionaria muito mais lentamente para diferentes fios.

(2) pode dormir se o conselheiro.

Bem e 2 vezes (pelo menos) mais 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() 
  {
//
  }
//+------------------------------------------------------------------+
olhou para o código anterior - sim
e OnChartEvent poderia usar um piggyback, que por defeito
EventSetCustomTimer
 
TheXpert:

Não. Sim, quis dizer que os gráficos são diferentes para os eventos 1 e 2

(1) Existe a suspeita de que funcionaria muito mais lentamente para diferentes fios.

(2) Pode dormir se a EA.

Bem e 2 vezes (pelo menos) mais lento.


É verdade o que eles dizem - mais sábias de manhã. :) Resolvi o problema. Até funcionou de forma muito elegante.

- Vamos introduzir o contador de mensagens enviadas event_idle

- Ao enviar o evento, enviar este contador para LPARAM EventChartCustom(chart, VM_IDLE, event_idle, 0, "");

- e, em seguida, no manipulador OnChartEvent, rake out todas as mensagens VM_IDLE até que o parâmetro de entrada LPARAM seja igual ao event_idle actual.

como esta

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

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

Desta forma, nunca haverá um exagero neste evento, uma vez que todos eles serão raspados.

Agora a velocidade está bem sem a enumeração do evento_idle queue enumeration :)

 
sergeev:

Mas surgiu um segundo problema, na medida em que a fila de mensagens não está a ser eliminada. transbordos.

Não consigo encontrar uma resposta à pergunta: como é que o transbordo de filas de eventos afecta o tamanho da RAM? Se a fila de eventos se revelou estar a transbordar, para onde vão os eventos que transbordaram? Será que parte da memória, reservada para aqueles acontecimentos que aconteceram "fora da história", é libertada?

Talvez as minhas perguntas não sejam terminologicamente correctas, mas (espero) captam a essência do problema.

 
Yedelkin:

Não consigo encontrar uma resposta para a pergunta: como é que uma fila de eventos transborda afecta o tamanho da RAM? Se a fila de eventos parecer estar a transbordar, para onde vão os eventos que transbordaram a fila?

A questão é essa: não o fazem. Acumulam-se.
 
sergeev:
A questão é essa: eles não vão a lado nenhum.

Isto é, se a fila de eventos ficar cheia, os eventos que transbordaram a fila "comem" a RAM, aumentando gradualmente o tamanho da RAM consumida? Mas isto está errado. Parece que os acontecimentos que "passaram da fila" deveriam finalmente libertar a memória reservada para eles.

... Um ano depois ainda não consegui obter uma resposta coerente à pergunta sobre o tamanho da fila do evento. Assim, ainda não está claro que frequência os eventos dos utilizadores devem ser enviados para que não transbordem a fila de eventos terminais...

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