Init() und DeInit() Ausführungsreihenfolge - Seite 21

 
fxsaber:
Das klingt nach Unsinn. Indikator-Kopierzeitgeber haben nichts miteinander zu tun.

Vor 500 Jahren klang die Behauptung, die Erde sei kugelförmig, auch für die meisten Menschen wie Unsinn.
OK, ich werde dieses Beispiel jetzt für einen Timer wiederholen.
 
Nikolai Semko:
Ok, ich werde dieses Beispiel jetzt für den Timer wiederholen.
Möchten Sie zeigen, dass der EvenKillTimer im alten Deinit-Zustand den EventSetTimer im neuen Init-Zustand beeinflussen wird?
 
Nikolai Semko:


Wenn es eindeutig ist.

Probieren Sie dieses primitive Beispiel aus. Sie werden die "Einzigartigkeit" verstehen, wenn Sie die TF wechseln.

In diesem Beispiel wird in OnInit ein Objekt mit den Koordinaten der aktuellen Zeit und des Preises erstellt. Bei OnCalculate bewegt sich dieses Objekt zusammen mit dem Preis.

Bei OnDeinit wird sie einfach (logisch) gelöscht.

Wenn man die TF umschaltet, erscheint das Objekt und verschwindet dann wieder.
Warum ist das so?
Denn manchmal löscht OnDeinit der alten TF das, was bereits im OnInit der neuen TF angelegt wurde. Es ist kein Fehler! Was sollte der Programmierer denken, der dieses Beispiel erstellt hat und diesen Zweig nicht gelesen hat?

In Ihrem Beispiel ist das grafische Objekt in allen TFs vorhanden, Sie müssen nur hineinzoomen, um es zu sehen.
 
fxsaber:
Möchten Sie zeigen, dass der EvenKillTimer im alten Deinit-Zustand den EventSetTimer im neuen Init-Zustand beeinflussen wird?

Ich habe mich geirrt. Ich bitte um Entschuldigung. Mein Fehler.
In der Tat stellte sich der Timer der neuen TF als überlebensfähiger, nicht tötbarerEventKillTimer der alten TF heraus. :)
Dateien:
KillTimer.mq5  6 kb
 
Sergey Pavlov:
In Ihrem Beispiel ist das grafische Objekt in allen TFs vorhanden, Sie müssen nur hineinzoomen, um es zu sehen.

Nein, ist es nicht. Sie wird manchmal durch die Deunit der alten TF entfernt.
 
Nikolai Semko:
Tatsächlich erwies sich der Timer der neuen TF als unverwüstlich und konnte durch den EventKillTimer der alten TF nicht getötet werden. :)
Ich bin sehr froh, dass sich meine Täuschung als Täuschung herausgestellt hat.
 
Nikolai Semko:

Nein, das ist es nicht. Sie wird manchmal durch Deinit der alten TF gelöscht.

Um die Aktualisierung von grafischen Objekten zu erzwingen, verwenden Sie den Befehl ChartRedraw(), um die Grafik neu zu zeichnen.

Fügen Sie dies zu Init und Deinit hinzu:

   ChartRedraw();
 
Sergey Pavlov:

Fügen Sie dies zu Init und Deinit hinzu:ChartRedraw();


Ich habe es ausprobiert. Dies ändert nichts an der Situation und kann nicht geändert werden, wenn das Objekt bereits entfernt wurde,ChartRedraw() wird es nicht wiederherstellen.
Ich schließe nicht aus, Sergey, dass diese "Besonderheit" der Zweideutigkeit der Ausführungsreihenfolge von OnInit der neuen TF und OnDeinit der alten TF vom Eisen abhängen kann. Denn verschiedene Threads, verschiedene Prozessoren mit unterschiedlicher Coprozessor-Architektur - das ist alles kompliziert und ich bin nicht gut darin. Aber die Tatsache, dass diese "Funktion" auf meinem Computer und auf den Computern anderer erscheint, ist nach diesem Thread zu urteilen, sicher.
Sie wollen also sagen, dass Sie dieses Beispiel auf Ihrem Computer ausprobiert haben, und wenn Sie zu TF wechseln, sehen Sie das Objekt immer?
Übrigens habe ich festgestellt, dass es sehr schwierig ist, das Objekt verschwinden zu lassen, wenn man die Candlesticks auf die maximale Größe vergrößert, d. h. der Bildschirm eine Mindestanzahl von Balken hat. Ich musste die TF 30 Mal wechseln, um das Objekt zu entfernen (d. h. DeUnit wurde später ausgelöst als Unit). Offensichtlich wird diese "Besonderheit" durch die Leistung des Gewindes beeinflusst. Dies ist eine Hypothese oder ein lauter Gedanke.
 
Комбинатор:
Ich bin sehr froh, dass sich meine Täuschung als Täuschung herausgestellt hat.

:) Es war keine Täuschung, nur eine Hypothese.
Danke für die Hypothese. Dank ihm undfxsaber wurde mir wieder bewusst, was eine Indikatorkopie ist. Der Timer gehört einfach zu dieser Kopie und stirbt zusammen mit ihr, auch wenn sich die TF ändert. Aber Objekte leben von sich selbst, auch wenn sie durch eine Kopie des Indikators erstellt werden, gehören sie nur zum Fenster. Jetzt verstehe ich, dass es keinen Sinn macht,EventKillTimer in die Deunit zu schreiben, denn der Timer wird sowieso sterben, wenn die Deunit bereits aufgerufen wurde.
 
Problemlösung
#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);
}

D.h. das ganze Problem ist das Hinzufügen EINER Zeile am Anfang eines beliebigen Indikators.


Bibliothekscode

// Библиотека делает синхронизированными 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
Dateien:
Init_Sync.mqh  3 kb
Grund der Beschwerde: