Seqüência de execução Init() e DeInit() - página 21

 
fxsaber:
Isso soa como um disparate. Os cronômetros indicadores de cópia nada têm a ver um com o outro.

500 anos atrás, a afirmação de que a Terra é esférica também soava como um disparate para a maioria das pessoas.
OK, vou refazer este exemplo para um temporizador agora.
 
Nikolai Semko:
Ok, agora vou refazer este exemplo para o temporizador.
Você quer mostrar que o EvenKillTimer no estado antigo deinit afetará o EventSetTimer no novo init?
 
Nikolai Semko:


Onde é inequívoco.

Experimente este exemplo primitivo. Você entenderá a "singularidade" ao trocar o TF.

Neste exemplo, um objeto com coordenadas de tempo e preço atuais é criado no OnInit. Na OnCalculate, este objeto se move junto com o preço.

No OnDeinit, ele é simplesmente (logicamente) apagado.

Ao trocar o TF, verifica-se que o objeto aparece e depois desaparece.
Por que isso acontece?
Porque às vezes o OnDeinit da antiga TF elimina o que já foi criado no OnInit da nova TF. Não é um bug! O que deve pensar o programador que criou este exemplo e não leu este ramo?

Em seu exemplo, o objeto gráfico está presente em todas as TFs, você só precisa fazer zoom para vê-lo.
 
fxsaber:
Você quer mostrar que o EvenKillTimer no estado antigo deinit afetará o EventSetTimer no novo init?

Eu estava errado. Minhas desculpas. Meu erro.
De fato, o temporizador do novo TF acabou se revelando sobrevivível, oEventKillTimer do antigo TF. :)
Arquivos anexados:
KillTimer.mq5  6 kb
 
Sergey Pavlov:
Em seu exemplo, o objeto gráfico está presente em todas as TFs, basta ampliar para vê-lo.

Não, não é. Ele é removido às vezes pela Deunit da antiga TF.
 
Nikolai Semko:
De fato, o temporizador do novo TF revelou-se resistente, não matável pelo EventKillTimer do antigo TF. :)
Muito feliz por minha ilusão ter se revelado uma ilusão.
 
Nikolai Semko:

Não, não é. Ele é apagado algumas vezes por Deinit da antiga TF.

Para forçar a atualização dos objetos gráficos, use o comando ChartRedraw() para redesenhar o gráfico.

Adicione isto ao Init e ao Deinit:

   ChartRedraw();
 
Sergey Pavlov:

Adicione isto ao Init e Deinit:ChartRedraw();


Experimentei-o. Isto não muda a situação, e não pode mudar, se o objeto já tiver sido removido,ChartRedraw() não o ressuscitará.
Não excluo, Sergey, que esta "peculiaridade" de ambigüidade da seqüência de execução do OnInit da nova TF e OnDeinit da antiga TF possa depender do hardware. Desde fios diferentes, processadores diferentes com arquitetura de coprocessador diferente - é tudo complicado e eu não sou bom nisso. Mas o fato deste "recurso" aparecer em meu computador e nos computadores de outros, a julgar por este tópico, é certo.
Então, você quer dizer que tentou este exemplo em seu computador e quando você troca de TF você sempre vê o objeto?
A propósito, notei que se você aumentar os castiçais até o tamanho máximo, ou seja, a tela tem um mínimo de barras, é muito difícil fazer o objeto desaparecer. Tive que trocar o TF 30 vezes para remover o objeto (ou seja, o DeUnit foi acionado mais tarde que a Unidade). Aparentemente, esta "peculiaridade" é afetada pelo desempenho dos fios. Isto é como uma hipótese ou um pensamento em voz alta.
 
Комбинатор:
Muito feliz por minha ilusão ter se revelado uma ilusão.

:) Não foi uma ilusão, apenas uma hipótese.
Obrigado pela hipótese. Graças a ele e aofxsaber eu tive uma nova rodada de conscientização do que é uma cópia indicadora. O temporizador simplesmente pertence a essa cópia e morre junto com ela, mesmo quando a TF muda. Mas os objetos vivem por si mesmos, mesmo que sejam criados por uma cópia do indicador, eles pertencem apenas à janela. Agora entendo que não adianta escreverEventKillTimer no Deunit, de qualquer forma, o temporizador morrerá se o Deunit já tiver sido chamado.
 
Solução do problema
#include <Init_Sync.mqh> // Делает синхронизированными Init/Deinit индикаторов

#property indicator_chart_window

#property indicator_buffers 1
#property indicator_plots   1
#property  indicator_color1  clrRed
#property  indicator_type1   DRAW_LINE

input int Input = 0;

double Buffer[];

int OnInit()
{
  SetIndexBuffer(0, Buffer);
  Print("Init");
  return(INIT_SUCCEEDED);
}

void OnDeinit( const int Reason )
{
  Print("DeInit");
}

void OnChartEvent( const int id,
                   const long& lparam,
                   const double& dparam,
                   const string& sparam )
{
}

void OnTimer()
{
}

int OnCalculate( const int rates_total,
                 const int prev_calculated,
                 const datetime &time[],
                 const double &open[],
                 const double &high[],
                 const double &low[],
                 const double &close[],
                 const long &tick_volume[],
                 const long &volume[],
                 const int &spread[] )
{
  ArrayCopy(Buffer, open, prev_calculated, prev_calculated);  
  return(rates_total);
}

Ou seja, todo o problema é adicionar UMA linha no início de qualquer indicador.


Código da biblioteca

// Библиотека делает синхронизированными Init/Deinit индикаторов.
// В индикаторе обязательно должны быть int OnInit(), OnDeinit, OnTimer и OnChartEvent.
// Которые не используется - прописать пустыми.

struct INIT_SYNC
{
  const string GlobalName;

  INIT_SYNC( void ) : GlobalName((string)::ChartID() + ::MQLInfoString(MQL_PROGRAM_NAME))
  {
  }

  bool Check( void ) const
  {
    static bool FirstRun = true;
    static bool FirstRunInit = true;

    if (FirstRun && (!::GlobalVariableCheck(this.GlobalName)))
    {
      FirstRun = (::GlobalVariableSet(this.GlobalName, 0) == 0);

      if (!FirstRun)
      {
        ::EventKillTimer();

        ::OnInit();
        FirstRunInit = false;
      }
    }
    else if (FirstRun)
      ::EventSetMillisecondTimer(1);
    else
      FirstRunInit = true;

    return(FirstRun || !FirstRunInit);
  }

  ~INIT_SYNC( void )
  {
    ::GlobalVariableDel(this.GlobalName);
  }
} Init_Sync;

#define  CHECK_INIT_SYNC if (Init_Sync.Check()) return

int OnInit( void )
{
  CHECK_INIT_SYNC INIT_SUCCEEDED;

  return(::OldOnInit());
}

#define OnInit OldOnInit

int OnCalculate( const int rates_total,
                 const int prev_calculated,
                 const datetime &time[],
                 const double &open[],
                 const double &high[],
                 const double &low[],
                 const double &close[],
                 const long &tick_volume[],
                 const long &volume[],
                 const int &spread[] )
{
  CHECK_INIT_SYNC prev_calculated;

  return(::OldOnCalculate(rates_total, prev_calculated, time, open, high, low, close, tick_volume, volume, spread));
}

#define OnCalculate OldOnCalculate

void OnTimer( void )
{
  CHECK_INIT_SYNC;

  ::OldOnTimer();
}

#define OnTimer OldOnTimer

void OnDeinit( const int Reason )
{
  CHECK_INIT_SYNC;

  ::OldOnDeinit(Reason);
}

#define OnDeinit OldOnDeinit

void OnChartEvent( const int id,
                   const long& lparam,
                   const double& dparam,
                   const string& sparam )
{
  CHECK_INIT_SYNC;

  ::OldOnChartEvent(id, lparam, dparam, sparam);
}

#define OnChartEvent OldOnChartEvent
Arquivos anexados:
Init_Sync.mqh  3 kb