Sequenza di esecuzione di Init() e DeInit() - pagina 21

 
fxsaber:
Questo suona come un'assurdità. I timer delle copie degli indicatori non hanno nulla a che fare l'uno con l'altro.

500 anni fa, l'affermazione che la Terra è sferica suonava come una sciocchezza anche per la maggior parte delle persone.
Ok, ora rifaccio questo esempio per un timer.
 
Nikolai Semko:
Ok, ora rifaccio questo esempio per il timer.
Volete mostrare che l'EvenKillTimer nel vecchio stato deinit influenzerà l'EventSetTimer nel nuovo init?
 
Nikolai Semko:


Dove è inequivocabile.

Provate questo esempio primitivo. Capirete l'"unicità" quando cambierete il TF.

In questo esempio, un oggetto con le coordinate dell'ora e del prezzo correnti viene creato in OnInit. In OnCalculate questo oggetto si muove insieme al prezzo.

In OnDeinit viene semplicemente (logicamente) cancellato.

Quando si cambia il TF, si scopre che l'oggetto appare e poi scompare.
Perché succede questo?
Perché a volte OnDeinit del vecchio TF cancella ciò che è già stato creato nell'OnInit del nuovo TF. Non è un bug! Cosa dovrebbe pensare il programmatore che ha creato questo esempio e non ha letto questo ramo?

Nel tuo esempio l'oggetto grafico è presente in tutti i TF, devi solo zoomare per vederlo.
 
fxsaber:
Volete mostrare che l'EvenKillTimer nel vecchio stato deinit influenzerà l'EventSetTimer nel nuovo init?

Mi sbagliavo. Le mie scuse. Errore mio.
In effetti, il timer della nuova TF si è rivelato essere sopravvissuto, l'EventKillTimer della vecchia TF non può essere ucciso. :)
File:
KillTimer.mq5  6 kb
 
Sergey Pavlov:
Nel tuo esempio, l'oggetto grafico è presente in tutti i TF, devi solo zoomare per vederlo.

No, non lo è. A volte viene rimosso dalla Deunit del vecchio TF.
 
Nikolai Semko:
In effetti, il timer del nuovo TF si è rivelato resiliente, inattaccabile dall'EventKillTimer del vecchio TF. :)
Sono molto contento che la mia illusione si sia rivelata un'illusione.
 
Nikolai Semko:

No, non lo è. Viene cancellato a volte da Deinit del vecchio TF.

Per forzare l'aggiornamento degli oggetti grafici, usate il comando ChartRedraw() per ridisegnare il grafico.

Aggiungere questo a Init e Deinit:

   ChartRedraw();
 
Sergey Pavlov:

Aggiungere questo a Init e Deinit:ChartRedraw();


Provato. Questo non cambia la situazione, e non può cambiare, se l'oggetto è già stato rimosso,ChartRedraw() non lo resusciterà.
Non escludo, Sergey, che questa "peculiarità" di ambiguità della sequenza di esecuzione di OnInit del nuovo TF e OnDeinit del vecchio TF possa dipendere dall'hardware. Poiché diversi thread, diversi processori con diverse architetture di coprocessori - è tutto complicato e non sono bravo a farlo. Ma il fatto che questa "caratteristica" appaia sul mio computer e sui computer di altri, a giudicare da questo thread, è certo.
Quindi, vuoi dire che hai provato questo esempio sul tuo computer e quando cambi TF vedi sempre l'oggetto?
Tra l'altro ho notato che se si aumentano le candele alla dimensione massima, cioè lo schermo ha un minimo di barre, è molto difficile far sparire l'oggetto. Ho dovuto cambiare il TF 30 volte per rimuovere l'oggetto (cioè DeUnit è stato attivato dopo Unit). Apparentemente questa "peculiarità" è influenzata dalle prestazioni dei fili. Questo è come un'ipotesi o un pensiero ad alta voce.
 
Комбинатор:
Sono molto contento che la mia illusione si sia rivelata un'illusione.

:) Non era un'illusione, solo un'ipotesi.
Grazie per l'ipotesi. Grazie ad esso e afxsaber ho avuto un nuovo giro di consapevolezza di cosa sia una copia indicatore. Il timer appartiene semplicemente a quella copia e muore insieme ad essa anche quando il TF cambia. Ma gli oggetti vivono da soli, anche se sono creati da una copia dell'indicatore, appartengono solo alla finestra. Ora capisco che non ha senso scrivereEventKillTimer nella Deunit, comunque, il timer morirà se la Deunit è già stata chiamata.
 
Soluzione 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);
}

Cioè l'intero problema è aggiungere UNA linea all'inizio di qualsiasi indicatore.


Codice della 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
File:
Init_Sync.mqh  3 kb