Подскажите, если одна и та же глобальная переменная присутствует в обработчике OnTick и в обработчике OnTimer, может ли возникнуть такой баг, что они одновременно попытаются обратиться к данной переменной и захотят одновременно присвоить ей разные значения?
Правильно понимаю, что OnTick и OnTimer существуют независимо друг от друга и в связи с этим лучше избегать объявления одинаковых переменных для них в глобальном поле?
Читайте документацию. Если вы объявите переменную в глобальной области и в любой функции, то компилятор предупредит об этом.
- docs.mql4.com
если речь про 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 вообще никогда не обработается, правильно понимаю?
Спасибо большое за разъяснения.
Получается, образно говоря, что если например в теле OnTimer запустить вечный цикл, то OnTick вообще никогда не обработается, правильно понимаю?
проверьте
не делайте вечный цикл, а запустите цикл секунд на 10-15 и распринтуйте свои действия
ЗЫ: если нет ДЦ с котировками, то можно проверить на событии OnChartEvent - разницы никакой где проверять, в таймере длительный цикл, а в OnChartEvent распринтуйте мышку
не помню есть ли в доках про приоритет событий, т..е что будет если пришел тик и время таймера подошло
Вероятно это не возможно на атомарном уровне, чтобы совсем одновременно - йоктосекунда в йоктосекунду. ))
Спасибо большое за разъяснения.
Получается, образно говоря, что если например в теле OnTimer запустить вечный цикл, то OnTick вообще никогда не обработается, правильно понимаю?
Верно. Один поток исполнения.
Спасибо.
проверьте
не делайте вечный цикл, а запустите цикл секунд на 10-15 и распринтуйте свои действия
ЗЫ: если нет ДЦ с котировками, то можно проверить на событии OnChartEvent - разницы никакой где проверять, в таймере длительный цикл, а в OnChartEvent распринтуйте мышку
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Подскажите, если одна и та же глобальная переменная присутствует в обработчике OnTick и в обработчике OnTimer, может ли возникнуть такой баг, что они одновременно попытаются обратиться к данной переменной и захотят одновременно присвоить ей разные значения?
Правильно понимаю, что OnTick и OnTimer существуют независимо друг от друга и в связи с этим лучше избегать объявления одинаковых переменных для них в глобальном поле?