Проблема: цикл обработки сообщений Windows и сброс локального контекста в start

 

Обнаружилась следующая проблема. Пишется dll-библиотека, подключаемая в МТ4 и выполняющая длительный расчет. На время расчета выводится диалоговое окно с кнопкой Прервать. Для того, чтобы кнопка работала, в процессе обсчета вызывается цикл:

                        MSG msg;
                        while (!fAbort && PeekMessage(&msg, NULL, 0, 0, TRUE))
                        if(!IsDialogMessage(hdlgAbort, &msg))
                        {
                            TranslateMessage(&msg);
                            DispatchMessage(&msg);
                        }

Как видно, обрабатываются только сообщения, относящиеся к выведенному окну, т.е. корректно.

Когда МТ4 в оффлайне все отлично. Когда МТ4 в онлайне, предположительно при приходе нового тика, все локальные переменные внутри start сбрасываются в начальные значения (напр. ноль), причем в start стоит защита от повторных входов:

int start()
{
Print("start");
  static datetime LastTime;
  static bool Processing;
  if(LastTime == Time[0]) return(0);
  if(Processing) return(0);
  LastTime = Time[0];
  Processing = true;
  Print("Enter");
  ...
  Processing = false;
  Print("Exit");
  return(0);
}

Если верить принтам, то вход внутрь start происходит, но все остальное пропускается (Enter и Exit не выводятся).

Каким же образом чистятся локальные переменные?

Вопрос: кто и что должен поправить, чтобы вывести диалог из dll без указанных побочных эффектов?

 

Пардон, не заметил к сожалению у себя последствия пресловутого копи-пейста, из-за чего сообщения переправлялись в Dispatch. Еще есть одно решение - путем переноса начинки start в другую функцию. ;-)

Но суть дела это не сильно меняет. ;-) Было ли у Вас так задумано или реализовали так по недосмотру, - в любом случае у Вас тоже ошибка. Локальные переменные должны распределяться на стеке и, соответственно, при повторных вложенных входах в функцию не портить данные, относящиеся к вызову, оставшемуся на стеке.

start [локальные переменные 1]
  DLL
    Message Pump
      start [локальные переменные 2]

Похоже, на исправление в МТ4 сложно рассчитывать, но хоть примите к сведению для следующих версий.

 

Как выяснилось, всё работает ещё более странно, чем я предполагал.

В тот момент, когда приходит новый тик, прекращается выполнение MQL-оператора вызова метода внутри DLL, который выполняет длительный расчет (видимо из-за message pump). В результате, расчет внутри DLL продолжается в фоне, а скрипт благополучно дорабатывает до конца, как будто работа DLL уже завершена, и все скриптовые переменные для блокировки повторного входа в расчет сбрасываются.

При формировании нового бара, запускается второй экземпляр расчета в DLL. И так далее.

Хотелось бы все-таки услышать мнение разработчиков. Нет никаких причин не анализировать скриптовый стек вызовов при приходе новых сообщений. Это баг.

 

Понятно: спасение утопающих - дело рук самих утопающих.

В общем, пришлось реализовать в DLL "семафор".

Причина обращения: