Последовательность выполнение Init() и DeInit() - страница 21

 
fxsaber:
Звучит, как глупость. Таймеры копий индикатора никакого отношения друг к другу не имеют.

500 лет назад для большинства людей утверждение, что Земля шарообразная, звучало тоже как глупость.
Хорошо, я сейчас переделаю этот пример под таймер. 
 
Nikolai Semko:
Хорошо, я сейчас переделаю этот пример под таймер. 
Вы хотите показать, что EvenKillTimer в старом деинит в состоянии повлияет на EventSetTimer в новом init?
 
Nikolai Semko:


Ну где же она однозначная.

Поюзайте этот примитивный пример. И поймете "однозначность" при переключения ТФ.

В этом примере в OnInit создается объект и координатами текущего времени и цены. В OnCalculate этот объек движется вместе с ценой.

В OnDeinit он просто ( что логично) удаляется.

При переключении ТФ выясняется, что объект то появляется, то и исчезает. 
Почему так происходит?
Потому, что иногда OnDeinit старого ТФ удаляет то что уже создано в OnInit нового ТФ. Это что не баг! Что должен должен думать программист, который создал этот пример и не читал данной ветки?

В Вашем примере графический объект присутствует на всех ТФ, просто нужно изменить масштаб чтобы его увидеть.
 
fxsaber:
Вы хотите показать, что EvenKillTimer в старом деинит в состоянии повлияет на EventSetTimer в новом init?

Был не прав. Извиняюсь. Лажанулся. 
Действительно, таймер нового ТФ оказался живучим, не убиваемым EventKillTimer старого ТФ. :)
Файлы:
KillTimer.mq5  6 kb
 
Sergey Pavlov:
В Вашем примере графический объект присутствует на всех ТФ, просто нужно изменить масштаб чтобы его увидеть.

Нет, не верно. Он удаляется иногда Деюнитом старого ТФ. 
 
Nikolai Semko:
Действительно, таймер нового ТФ оказался живучим, не убиваемым EventKillTimer старого ТФ. :)
Очень рад что мой бред оказался бредом
 
Nikolai Semko:

Нет, не верно. Он удаляется иногда Деюнитом старого ТФ. 

Для принудительного обновления графических объектов используйте команду на перерисовку графика ChartRedraw().

Добавьте в Init и Deinit вот это:

   ChartRedraw();
 
Sergey Pavlov:

Добавьте в Init и Deinit вот это: ChartRedraw();


Попробовал. Это не меняет ситуации, да и не может менять, если объект уже удален, ChartRedraw() его не воскресит.
Я не исключаю, Сергей, что эта "особенность" неоднозначности последовательности выполнения OnInit нового ТФ и OnDeinit старого ТФ может зависить от железа. Т.к. разные потоки, разные процессоры с разной архитектурой сопроцессоров - это все сложно и я в этом не силен. Но то что эта "особенность" проявляется на моем компьютере и на компьютере других судя по этой ветке, то это точно. 
То есть, Вы хотите сказать что пробовали этот пример на своем компьютере и при переключении ТФ вы всегда видели объект?
Я кстати заметил, что если свечи увеличить до максимального размера, т.е. на экране мин кол-во баров, то очень тяжело добиться исчезновение объекта. Мне приходилось переключать ТФ раз 30 чтобы произошло удаление объекта ( т.е. Деюнит сработал позже Юнита).  Видимо на эту "особенность" влияет производительность потоков. Это как гипотеза или мысть вслух.
 
Комбинатор:
Очень рад что мой бред оказался бредом

:) Это был не бред, а лишь гипотеза. 
Спасибо за гипотезу. Благодаря ей и fxsaber у меня произошел новый виток осознания, что такое копия индикатора. Просто таймер принадлежит этой копии и умирает вместе с ней даже при смене ТФ. А объекты живут сами по себе, даже если созданы копией индикатора, они принадлежат только окну. Теперь я понимаю, что прописывать в Деюните EventKillTimer смысла никакого нет, все равно таймер умрет если уже произошло обращение к Деюниту.
 
Решение проблемы
#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);
}

Т.е. вся проблема - это добавление ОДНОЙ строки в начале любого индикатора.


Код библиотеки

// Библиотека делает синхронизированными 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
Причина обращения: