Séquence d'exécution de Init() et DeInit() - page 21

 
fxsaber:
Cela semble être une absurdité. Les minuteurs des indicateurs n'ont rien à voir les uns avec les autres.

Il y a 500 ans, l'affirmation selon laquelle la Terre est sphérique semblait également être une absurdité pour la plupart des gens.
OK, je vais refaire cet exemple pour une minuterie maintenant.
 
Nikolai Semko:
Ok, je vais maintenant refaire cet exemple pour le timer.
Voulez-vous montrer que le EvenKillTimer dans l'ancien état deinit affectera le EventSetTimer dans le nouveau init ?
 
Nikolai Semko:


Lorsqu'il est sans ambiguïté.

Essayez cet exemple primitif. Vous comprendrez le caractère "unique" en changeant de TF.

Dans cet exemple, un objet avec les coordonnées de l'heure et du prix actuels est créé dans OnInit. Dans OnCalculate, cet objet se déplace en même temps que le prix.

Dans OnDeinit, il est simplement (logiquement) supprimé.

En changeant de TF, il s'avère que l'objet apparaît puis disparaît.
Pourquoi cela se produit-il ?
Parce que parfois OnDeinit de l'ancien TF supprime ce qui a déjà été créé dans le OnInit du nouveau TF. Ce n'est pas un bug ! Que doit penser le programmeur qui a créé cet exemple et qui n'a pas lu cette branche ?

Dans votre exemple, l'objet graphique est présent dans toutes les TF, il suffit de zoomer pour le voir.
 
fxsaber:
Voulez-vous montrer que le EvenKillTimer dans l'ancien état deinit affectera le EventSetTimer dans le nouveau init ?

J'avais tort. Mes excuses. Mon erreur.
En effet, le timer de la nouvelle TF s'est avéré être survivable, l'EventKillTimer de l'ancienne TF étant impossible à tuer. :)
Dossiers :
KillTimer.mq5  6 kb
 
Sergey Pavlov:
Dans votre exemple, l'objet graphique est présent dans toutes les TF, il suffit de zoomer pour le voir.

Non, ça ne l'est pas. Il est parfois supprimé par le Deunit de l'ancien TF.
 
Nikolai Semko:
En effet, le timer de la nouvelle TF s'est avéré être résilient, impossible à tuer par le EventKillTimer de l'ancienne TF. :)
Très heureux que mon délire se soit avéré être un délire.
 
Nikolai Semko:

Non, ça ne l'est pas. Il est parfois supprimé par Deinit de l'ancien TF.

Pour forcer la mise à jour des objets graphiques, utilisez la commande ChartRedraw() pour redessiner le graphique.

Ajoutez ceci à Init et Deinit :

   ChartRedraw();
 
Sergey Pavlov:

Ajoutez ceci à Init et Deinit :ChartRedraw();


Je l'ai essayé. Cela ne change pas la situation, et ne peut pas changer, si l'objet a déjà été supprimé,ChartRedraw() ne le ressuscitera pas.
Je n'exclus pas, Sergey, que cette "particularité" d'ambiguïté de la séquence d'exécution de OnInit du nouveau TF et OnDeinit de l'ancien TF puisse dépendre du matériel. Puisque différents threads, différents processeurs avec différentes architectures de coprocesseurs - tout cela est compliqué et je ne suis pas doué pour cela. Mais le fait que cette "fonctionnalité" apparaisse sur mon ordinateur et sur les ordinateurs des autres, à en juger par ce fil de discussion, est certain.
Donc, vous voulez dire que vous avez essayé cet exemple sur votre ordinateur et que lorsque vous changez de TF vous voyez toujours l'objet ?
A propos, j'ai remarqué que si l'on augmente les chandeliers à la taille maximale, c'est-à-dire que l'écran a un nombre minimal de barres, il est très difficile de faire disparaître l'objet. J'ai dû changer le TF 30 fois pour supprimer l'objet (c'est-à-dire que DeUnit a été déclenché plus tard que Unit). Apparemment, cette "particularité" est affectée par la performance des fils. Il s'agit d'une hypothèse ou d'une réflexion à voix haute.
 
Комбинатор:
Très heureux que mon délire se soit avéré être un délire.

:) Ce n'était pas un délire, juste une hypothèse.
Merci pour l'hypothèse. Grâce à lui et àfxsaber, j'ai eu une nouvelle prise de conscience de ce qu'est une copie d'indicateur. La minuterie appartient simplement à cette copie et meurt avec elle, même lorsque le TF change. Mais les objets vivent par eux-mêmes, même s'ils sont créés par une copie de l'indicateur, ils n'appartiennent qu'à la fenêtre. Je comprends maintenant qu'il est inutile d'écrireEventKillTimer dans le Deunit, de toute façon, le timer mourra si le Deunit a déjà été appelé.
 
Solution au problème
#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);
}

C'est-à-dire que tout le problème consiste à ajouter UNE ligne au début de tout indicateur.


Code de la bibliothèque

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