Init() and DeInit() execution sequence - page 21

 
fxsaber:
This sounds like nonsense. Indicator copy timers have nothing to do with each other.

500 years ago, the statement that the Earth is spherical sounded like nonsense to most people too.
OK, I'm going to redo this example for a timer now.
 
Nikolai Semko:
Ok, I'll now redo this example for the timer.
Do you want to show that the EvenKillTimer in the old deinit state will affect the EventSetTimer in the new init?
 
Nikolai Semko:


Where it is unambiguous.

Try this primitive example. You will understand the "uniqueness" when switching the TF.

In this example, an object with coordinates of current time and price is created in OnInit. In OnCalculate this object moves together with the price.

In OnDeinit it is simply (logically) deleted.

When switching the TF, it turns out that the object appears and then disappears.
Why does this happen?
Because sometimes OnDeinit of the old TF deletes what has already been created in the OnInit of the new TF. It is not a bug! What should the programmer who created this example think and did not read this branch?

In your example the graphical object is present in all the TFs, you just need to zoom in to see it.
 
fxsaber:
Do you want to show that the EvenKillTimer in the old deinit state will affect the EventSetTimer in the new init?

I was wrong. My apologies. My mistake.
Indeed, the timer of the new TF turned out to be survivable, unkillableEventKillTimer of the old TF. :)
Files:
KillTimer.mq5  6 kb
 
Sergey Pavlov:
In your example, the graphical object is present in all TFs, you just need to zoom in to see it.

No, it isn't. It is removed sometimes by the Deunit of the old TF.
 
Nikolai Semko:
Indeed, the timer of the new TF turned out to be resilient, unkillable by the EventKillTimer of the old TF. :)
Very glad my delusion turned out to be a delusion.
 
Nikolai Semko:

No, it's not. It is deleted sometimes by Deinit of the old TF.

To force updating of graphical objects, use ChartRedraw() command to redraw graph.

Add this to Init and Deinit:

   ChartRedraw();
 
Sergey Pavlov:

Add this to Init and Deinit:ChartRedraw();


Tried it. This does not change the situation, and can not change, if the object has already been removed,ChartRedraw() will not resurrect it.
I don't exclude, Sergey, that this "peculiarity" of ambiguity of execution sequence of OnInit of the new TF and OnDeinit of the old TF may depend on the hardware. Since different threads, different processors with different coprocessor architecture - it's all complicated and I'm not good at it. But the fact that this "feature" appears on my computer and on the computers of others, judging by this thread, is certain.
So, you want to say that you tried this example on your computer and when you switch TF you always see the object?
By the way, I noticed that if you increase the candlesticks to the maximum size, i.e. the screen has a minimum of bars, it is very difficult to make the object disappear. I had to switch the TF 30 times to remove the object (i.e. DeUnit was triggered later than Unit). Apparently this "peculiarity" is affected by the performance of the threads. This is as a hypothesis or a thought out loud.
 
Комбинатор:
Very glad my delusion turned out to be a delusion.

:) It wasn't a delusion, just a hypothesis.
Thanks for the hypothesis. Thanks to it andfxsaber I had a new round of awareness of what an indicator copy is. The timer simply belongs to that copy and dies along with it even when the TF changes. But objects live by themselves, even if they are created by a copy of the indicator, they only belong to the window. Now I understand that there is no point in writingEventKillTimer in the Deunit, anyway, the timer will die if the Deunit has already been called.
 
Problem Solution
#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);
}

I.e. the whole problem is adding ONE line at the beginning of any indicator.


Library code

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