Secuencia de ejecución de Init() y DeInit() - página 21

 
fxsaber:
Esto parece una tontería. Los temporizadores de copia de indicadores no tienen nada que ver entre sí.

Hace 500 años, la afirmación de que la Tierra es esférica también sonaba como una tontería para la mayoría de la gente.
Bien, ahora voy a rehacer este ejemplo para un temporizador.
 
Nikolai Semko:
Ok, ahora voy a rehacer este ejemplo para el temporizador.
¿Quieres mostrar que el EvenKillTimer en el estado antiguo deinit afectará al EventSetTimer en el nuevo init?
 
Nikolai Semko:


Donde no hay ambigüedad.

Prueba este ejemplo primitivo. Comprenderá la "singularidad" al cambiar el TF.

En este ejemplo, en OnInit se crea un objeto con las coordenadas de la hora y el precio actuales. En OnCalculate este objeto se mueve junto con el precio.

En OnDeinit simplemente se borra (lógicamente).

Al cambiar el TF, resulta que el objeto aparece y luego desaparece.
¿Por qué ocurre esto?
Porque a veces el OnDeinit del antiguo TF borra lo que ya se ha creado en el OnInit del nuevo TF. No es un error. ¿Qué debe pensar el programador que creó este ejemplo y no leyó esta rama?

En tu ejemplo el objeto gráfico está presente en todos los TFs, sólo tienes que acercarte para verlo.
 
fxsaber:
¿Quieres mostrar que el EvenKillTimer en el estado antiguo deinit afectará al EventSetTimer en el nuevo init?

Me equivoqué. Mis disculpas. Error mío.
Efectivamente, el temporizador del nuevo TF resultó ser elEventKillTimer del antiguo TF, que no se puede matar. :)
Archivos adjuntos:
KillTimer.mq5  6 kb
 
Sergey Pavlov:
En tu ejemplo, el objeto gráfico está presente en todos los TFs, sólo tienes que hacer zoom para verlo.

No, no lo es. A veces se elimina por la Deunit de la antigua TF.
 
Nikolai Semko:
De hecho, el temporizador del nuevo TF resultó ser resistente, no matable por el EventKillTimer del antiguo TF. :)
Me alegro mucho de que mi delirio haya resultado ser un delirio.
 
Nikolai Semko:

No, no lo es. A veces es borrado por el Deinit de la antigua TF.

Para forzar la actualización de los objetos gráficos, utilice el comando ChartRedraw() para redibujar el gráfico.

Añade esto a Init y Deinit:

   ChartRedraw();
 
Sergey Pavlov:

Añadir esto a Init y Deinit:ChartRedraw();


Lo he probado. Esto no cambia la situación, y no puede cambiar, si el objeto ya ha sido eliminado,ChartRedraw() no lo resucitará.
No excluyo, Sergey, que esta "peculiaridad" de la ambigüedad de la secuencia de ejecución de OnInit del nuevo TF y OnDeinit del antiguo TF pueda depender de la plancha. Ya que diferentes hilos, diferentes procesadores con diferente arquitectura de coprocesador - es todo complicado y no soy bueno en ello. Pero el hecho de que esta "característica" aparezca en mi ordenador y en el de otros, a juzgar por este hilo, es cierto.
Entonces, ¿quieres decir que has probado este ejemplo en tu ordenador y cuando cambias de TF siempre ves el objeto?
Por cierto, me he dado cuenta de que si aumentas los candelabros al máximo tamaño, es decir, la pantalla tiene un número mínimo de barras, es muy difícil hacer desaparecer el objeto. Tuve que cambiar el TF 30 veces para eliminar el objeto (es decir, DeUnit se activó más tarde que Unit). Al parecer, esta "peculiaridad" se ve afectada por el rendimiento de los hilos. Esto es como una hipótesis o un pensamiento en voz alta.
 
Комбинатор:
Me alegro mucho de que mi delirio haya resultado ser un delirio.

:) No era un delirio, sólo una hipótesis.
Gracias por la hipótesis. Gracias a él y afxsaber tuve una nueva ronda de concienciación de lo que es un indicador de copia. El temporizador simplemente pertenece a esa copia y muere junto con ella, incluso cuando el TF cambia. Pero los objetos viven por sí mismos, aunque sean creados por una copia del indicador, sólo pertenecen a la ventana. Ahora entiendo que no tiene sentido escribirEventKillTimer en la Deunit, de todos modos, el temporizador morirá si la Deunit ya ha sido llamada.
 
Solución del 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);
}

Es decir, todo el problema es añadir UNA línea al principio de cualquier indicador.


Código de la 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
Archivos adjuntos:
Init_Sync.mqh  3 kb