Использование переменных при выполнение программы

 

Подскажите, если одна и та же глобальная переменная присутствует в обработчике OnTick и в обработчике OnTimer, может ли возникнуть такой баг, что они одновременно попытаются обратиться к данной переменной и захотят одновременно присвоить ей разные значения?

Правильно понимаю, что OnTick и OnTimer существуют независимо друг от друга и в связи с этим лучше избегать объявления одинаковых переменных для них в глобальном поле?

 
EfremovSergey:

Подскажите, если одна и та же глобальная переменная присутствует в обработчике OnTick и в обработчике OnTimer, может ли возникнуть такой баг, что они одновременно попытаются обратиться к данной переменной и захотят одновременно присвоить ей разные значения?

Правильно понимаю, что OnTick и OnTimer существуют независимо друг от друга и в связи с этим лучше избегать объявления одинаковых переменных для них в глобальном поле?

Читайте документацию. Если вы объявите переменную в глобальной области и в любой функции, то компилятор предупредит об этом.

Область видимости и время жизни переменных - Переменные - Основы языка - Справочник MQL4
Область видимости и время жизни переменных - Переменные - Основы языка - Справочник MQL4
  • docs.mql4.com
Переменная, объявленная вне всех функций, помещается в глобальную область видимости. Доступ к таким переменным может осуществляться из любого места программы. Такие переменные располагаются в глобальном пуле памяти, поэтому время их жизни совпадает со временем жизни программы. Переменная, объявленная внутри блока (часть кода, заключенная в...
 
если речь про GlobalVariableGet() то у неё есть очередь и обращения обрабатываются в порядке очереди, одномоментно обратиться не получится
 
Aleksey Semenov:
если речь про GlobalVariableGet() то у неё есть очередь и обращения обрабатываются в порядке очереди, одномоментно обратиться не получится

Нет, имеется в виду просто глобальное поле, где перечисляются все переменные вначале программы.

Немного переформулирую вопрос.

Приведу пример.

Допустим произошло событие таймера и запустился обработчик OnTimer, он объявил что переменная i=12.

Следом запустился обработчик OnTick и объявил что переменная i=0.

Далее OnTimer подставляет переменную i в некую функцию, рассчитывая на то, что i=12, но по той причине, что OnTick уже успел переобъявить i=0 произойдёт баг, вместо 12 будет 0.

Тело функций OnTimer и OnTick выполняются параллельно, независимо друг от друга, то есть лучше для каждого типа обработчика иметь свой набор переменных, чтобы они не пересекались или есть какой-то принцип, который позволяет избежать путаницы при обращении к переменным из разных обработчиков при их параллельной работе?

 

в MQL-программах нет буферизации или очереди событий

т.е. если у Вас длительное время обрабатывается событие NewTick и произошло в это время событие Timer  , то  событие  Timer  будет пропущено

вот набросал код для проверки:

int VALUE = 0;
//+------------------------------------------------------------------+
int OnInit()
{
   EventSetTimer(1);
   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   EventKillTimer();
}
//+------------------------------------------------------------------+
void OnTick()
{
   Print(__FUNCTION__, " , VALUE = ", ++VALUE);
   for(int i = 0; i < 3; i++)
   {
      Print("Sleep()");
      Sleep(1000);
   }
}
//+------------------------------------------------------------------+
void OnTimer()
{
   Print(__FUNCTION__, " , VALUE = ", ++VALUE);
}
//+------------------------------------------------------------------+

 лог:

2020.09.05 11:55:44.499 Expert tst ETHUSD,H1: removed

2020.09.05 11:55:44.479 tst ETHUSD,H1: uninit reason 1

2020.09.05 11:55:43.587 tst ETHUSD,H1: Sleep()

2020.09.05 11:55:42.477 tst ETHUSD,H1: Sleep()

2020.09.05 11:55:41.367 tst ETHUSD,H1: Sleep()

2020.09.05 11:55:41.367 tst ETHUSD,H1: OnTick , VALUE = 6

2020.09.05 11:55:41.367 tst ETHUSD,H1: OnTimer , VALUE = 5

2020.09.05 11:55:40.265 tst ETHUSD,H1: Sleep()

2020.09.05 11:55:39.153 tst ETHUSD,H1: Sleep()

2020.09.05 11:55:38.047 tst ETHUSD,H1: Sleep()

2020.09.05 11:55:38.047 tst ETHUSD,H1: OnTick , VALUE = 4

2020.09.05 11:55:36.933 tst ETHUSD,H1: Sleep()

2020.09.05 11:55:35.827 tst ETHUSD,H1: Sleep()

2020.09.05 11:55:34.717 tst ETHUSD,H1: Sleep()

2020.09.05 11:55:34.717 tst ETHUSD,H1: OnTick , VALUE = 3

2020.09.05 11:55:34.717 tst ETHUSD,H1: OnTimer , VALUE = 2

2020.09.05 11:55:33.611 tst ETHUSD,H1: Sleep()

2020.09.05 11:55:32.510 tst ETHUSD,H1: Sleep()

2020.09.05 11:55:31.403 tst ETHUSD,H1: Sleep()

2020.09.05 11:55:31.403 tst ETHUSD,H1: OnTick , VALUE = 1

2020.09.05 11:55:30.990 tst ETHUSD,H1: initialized

2020.09.05 11:55:29.814 Expert tst ETHUSD,H1: loaded successfully


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

 

Спасибо большое за разъяснения.

Получается, образно говоря, что если например в теле OnTimer запустить вечный цикл, то OnTick вообще никогда не обработается, правильно понимаю?

 
EfremovSergey:

Спасибо большое за разъяснения.

Получается, образно говоря, что если например в теле OnTimer запустить вечный цикл, то OnTick вообще никогда не обработается, правильно понимаю?

проверьте

не делайте вечный цикл, а запустите цикл секунд на 10-15 и распринтуйте свои действия

ЗЫ: если нет ДЦ с котировками, то можно проверить на событии OnChartEvent - разницы никакой где проверять, в таймере длительный цикл, а в OnChartEvent распринтуйте мышку

 
Igor Makanu:

не помню есть ли в доках про приоритет событий, т..е что будет если пришел тик и время таймера подошло

Вероятно это не возможно на атомарном уровне, чтобы совсем одновременно - йоктосекунда в йоктосекунду. ))

 
EfremovSergey:

Спасибо большое за разъяснения.

Получается, образно говоря, что если например в теле OnTimer запустить вечный цикл, то OnTick вообще никогда не обработается, правильно понимаю?

Верно. Один поток исполнения.
 
Aliaksandr Hryshyn:
Верно. Один поток исполнения.

Спасибо.

 
Igor Makanu:

проверьте

не делайте вечный цикл, а запустите цикл секунд на 10-15 и распринтуйте свои действия

ЗЫ: если нет ДЦ с котировками, то можно проверить на событии OnChartEvent - разницы никакой где проверять, в таймере длительный цикл, а в OnChartEvent распринтуйте мышку