Init()およびDeInit()実行シーケンス - ページ 21

 
fxsaber:
これはナンセンスな話だと思う。インジケーター・コピー・タイマーは互いに関係ありません。

500年前、「地球は球形である」という言葉は、ほとんどの人にとってもナンセンスに聞こえました。
よし、今からタイマー用にこの例をやり直そう。
 
Nikolai Semko:
では、この例をタイマーのためにやり直します。
古いdeinit状態のEvenKillTimerが新しいinitのEventSetTimerに 影響することを示したいのでしょうか?
 
Nikolai Semko:


曖昧でないところ。

この原始的な例を試してみてください。TFを交換すると "らしさ "がわかる。

この例では、OnInitで現在時刻と 価格の座標を持つオブジェクトを生成しています。OnCalculateでは、このオブジェクトは価格と一緒に移動します。

OnDeinitでは単純に(論理的に)削除される。

TFを切り替えると、オブジェクトが表示されたり消えたりすることが判明。
なぜ、このようなことが起こるのでしょうか。
なぜなら、古いTFのOnDeinitで、新しいTFのOnInitですでに作成されたものが削除 されることが あるからです。バグではありません!この例を作ったプログラマは、このブランチを読まずにどう考えるべきでしょうか?

この例では、グラフィカルなオブジェクトはすべてのTFに存在し、それを見るにはズームインする必要があります。
 
fxsaber:
古いdeinit状態のEvenKillTimerが新しいinitのEventSetTimerに影響することを示したいのでしょうか?

私は間違っていた。申し訳ございませんでした。
確かに、新TFのタイマーは旧TFのEventKillTimerを 殺せないサバイバブルであることが判明しました。:)
ファイル:
KillTimer.mq5  6 kb
 
Sergey Pavlov:
この例では、グラフィカルなオブジェクトはすべてのTFに存在し、それを見るにはズームインする必要があります。

いいえ、そんなことはありません。旧TFのDeunitで削除されることもあります。
 
Nikolai Semko:
実際、新しいTFのタイマーは、古いTFのEventKillTimerでは殺すことができない弾力性のあるものであることが判明した。:)
妄想が妄想に変わってとてもうれしいです。
 
Nikolai Semko:

いいえ、そんなことはありません。旧TFのDeinitで削除されることがあります。

グラフオブジェクトを強制的に更新するには、ChartRedraw() コマンドでグラフを再描画してください。

InitとDeinitに追加してください。

   ChartRedraw();
 
Sergey Pavlov:

InitとDeinit:ChartRedraw()にこれを追加 します。


試してみました。これは、オブジェクトが既に削除されている場合、ChartRedraw()はそれを復活させない、状況を変更しない、とすることはできません。
新TFのOnInitと旧TFのOnDeinitの実行順序が曖昧になるという「特異性」は、ハードウェアに依存する可能性も否定できませんね。スレッドも違えば、プロセッサもコプロセッサのアーキテクチャも違うので、すべてが複雑で、私は得意ではありません。しかし、このスレッドから判断するに、この「機能」が私のパソコンや他の人のパソコンに現れていることは確かです。
つまり、この例を自分のパソコンで試して、TFを切り替えると必ずオブジェクトが見えると言いたいのでしょうか?
ところで、ローソク足のサイズを最大まで大きくすると、つまり画面に最小限のバーがあると、オブジェクトを消すのが非常に難しくなることに気づきました。オブジェクトを削除するために30回TFを切り替える必要があった(つまり、UnitよりDeUnitの方が後に発動した)。どうやらこの「クセ」は、糸の性能に影響されるようです。これは、仮説や思いつきとしてです。
 
Комбинатор:
妄想が妄想に変わってとてもうれしいです。

:)妄想ではなく、ただの仮説でした。
仮説をありがとうございました。それとfxsaberの おかげで、インジケーターコピーとは何かということを改めて認識することができました。タイマーは単にそのコピーに属するもので、TFが変わっても一緒に死んでしまうのです。しかし、オブジェクトはそれ自体で生きており、たとえインジケーターのコピーで作られたとしても、それはウィンドウにしか属さない。Deunitの中にEventKillTimerを 記述しても意味がないことは理解できました。とにかく、Deunitがすでに呼び出されていればタイマーは死んでしまうのです。
 
問題解決
#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);
}

すなわち、すべての問題は、任意のインジケータの先頭にONEラインを追加することです。


図書館コード

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