Технический вопрос по терминалу MT4 - вызов другого процесса из индюка в MT4 приводит к поступлению новых тиков в start() и проблемам синхронизации - страница 2

 
Gorinych:

Это будет безумно медленно :(

Даже внутри одного процесса МТ4 данные между индюком и советником передавать нерентабельно (разница в скорости чуть ли не на порядки в сравнении со встраиванием кода индюка прямо в советник)...

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

индюк в крайнем случае на втором терминале можно исполнить в виде советника, так будет работать значительно быстрее, не надо обрабатывать всякую графику...
 
Gorinych:

А я наблюдаю следующее явление, когда где-то в дебрях старт() вызывается API Математики MathLink, которое вызывает другой процесс: не смотря на то, что старт() для прошлого тика ещё не завершился (другой процесс работает долго, но поток простаивает ожидая результатов), вызывается старт() для нового тика. Т.е. получается, что предлагается обработать новый тик, при том, что ещё не завершена обработка старого тика... Ну, и соответственно, в случае, когда я просто буду отсеивать такие "неправильные" старт(), IndicatorCounted() будет выдавать впоследствии неправильные значения...

Один товарищ где-то с год назад нарыл замечательный нюанс... (собственно, нюанс нарыл я, а товарищ нарыл глюк ;-) ) 

В Windows можно сделать функцию типа ProcessMessages(), которая выглядит примерно вот так:

.

MSG msg = {0};
while(::PeekMessage(&msg, 0, 0, 0, PM_REMOVE) != 0)
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
.

Понятно, что она работает для какого-то конкретного UI потока. Собственно, можно создавать несколько UI потоков в одном процессе- никто не мешает (тьфу-тьфу). Очень удобно.

При помощи этой функции он размораживал себе UI метатрейдера на момент обработки данных в Dll, но засчет того, что он делал ArrayCopyRates(), а также работал с буферами индикаторов, в итоге появлялись сложноотлавливаемые глюки с памятью, из-за которых терминал "падал".

.

Посему... можно предположить, что MathLink() как-то неявно выполняет обработку сообщений (может быть, им показалось, что так будет лучше- кто знает этих умных программистов, что им пришло в голову).

.

А это, в свою очередь, означает, что MathLink надо как-то вызывать из собственного нового потока, в то время, как поток GUI метатрейдера будет молотить в небольшом цикле типа

for(;;)

{

if(ВсеГотово()) { break; }

Sleep(100);
}
.

Sleep должен быть не метатрейдеровский- в эксперте он не работает как задержка.

.

Собственно, это единственный здравый вариант с ожиданием, поскольку если поток из индикатора не вышел, а GUI "отвисло", то это чревато *большими* проблемами...

.

.

Но никто не мешает сделать по-умному- данные шлются наружу, на обработку, в файл, например или в горячо любимую маппированную память. Когда данные обработаны- внешний процесс шлет на окно (WindowHandle) команду на рефреш, при этом, ясное дело, вызывается индикатор. Индикатор читает результаты обработки в формате дата-время / значение индикатора и рисует. (Дата-время на тот случай, если индексы буферов уже поменялись- т.е. данные будут помещаться при помощи поиска индекса бара по дате-времени, такой поиск можно сделать не бинарный, а со сложностью O(1), я делал). Быстро и хорошо.

.

При таком раскладе UI не "вешается", и проблем особых нет.

 
jartmailru:

Понятно, что она работает для какого-то конкретного UI потока. Собственно, можно создавать несколько UI потоков в одном процессе- никто не мешает (тьфу-тьфу). Очень удобно.

Ну-ну...

При помощи этой функции он размораживал себе UI метатрейдера на момент обработки данных в Dll, но засчет того, что он делал ArrayCopyRates(), а также работал с буферами индикаторов, в итоге появлялись сложноотлавливаемые глюки с памятью, из-за которых терминал "падал".

Гг :), что собственно и неудивительно.

 
jartmailru:

неверно

неверно

 
gip:

неверно

неверно


Замечательно ;-), очень рад
 

Уважаемые господа, всем большое спасибо за высказанные соображения и участие. Пока ничего конкретного сказать не могу, надо подумать и поэкспериментировать... Буду проверять и решать вопрос... Спасибо большое!


Хочу лишь чуть прокомментировать один момент:

TheXpert:

Это правильная обработка.

Я уважаю Ваше мнение, однако в данном конкретном случае считаю, что Вы ошибаетесь. Если вы один из людей, принимающих решения по МТ, я готов обосновать своё мнение. В противном случае останемся при своих :)
 
Gorinych:

Хочу лишь чуть прокомментировать один момент:

Я уважаю Ваше мнение, однако в данном конкретном случае считаю, что Вы ошибаетесь. Если вы один из людей, принимающих решения по МТ, я готов обосновать своё мнение. В противном случае останемся при своих :)

Совершенно согласен с Вами относительно того, что текущая реализация МТ4 неверная (МТ5 по данному вопросы пока нет времени проверять). Не дело прикладника разруливать проблемы реентерабельности, которые должны решать разработчики плафтормы. Я пытался устранить данную проблему уже давно. Постил сообщения вот тут - http://www.metatrader4.com/ru/forum/14018. Закончилось дело тем, что действительно ручками приходится блокировать последующие вызовы start-а с помощью вспомогательных функций в своей библиотеке:

extern CRITICAL_SECTION csLock;
static int Lock = 0;

MT4_EXPFUNC int __stdcall SetLock(void)
{
EnterCriticalSection(&csLock);
Lock++;
TRACE("++Lock = %d", Lock);
LeaveCriticalSection(&csLock);
return Lock;
}

MT4_EXPFUNC int __stdcall CheckLock(void)
{
return Lock;
}

MT4_EXPFUNC int __stdcall ClearLock(void)
{
EnterCriticalSection(&csLock);
Lock--;
TRACE("--Lock = %d", Lock);
LeaveCriticalSection(&csLock);
return Lock;
}

 
Gorinych:
Если вы один из людей, принимающих решения по МТ, я готов обосновать своё мнение.

Нет, я всего лишь скромный системный программист :) использующий терминал. Мнение с интересом выслушаю, и свое скажу.

1. Проблемы работы в разных потоках и синхронизации, создаваемые пользователем, а не терминалом, пользователем же должны разруливаться. Это не так сложно.

Переделать асинхронный вызов в синхронный -- это же несложно, и это даже не самый лучший выход.

2. Со стороны пользователя реализовать асинхронную схему работы и синхронизацию будет на порядок проще.

 
TheXpert:

Нет, я всего лишь скромный программист :) использующий терминал. Мнение с интересом выслушаю, и свое скажу.

1. Проблемы работы в разных потоках и синхронизации, создаваемые пользователем, а не терминалом, пользователем же должны разруливаться. Это не так сложно.

Переделать асинхронный вызов в синхронный -- это же несложно, и это даже не самый лучший выход.

2. Со стороны пользователя реализовать асинхронную схему работы и синхронизацию будет на порядок проще.

Не согласен ;-). С какой стати прикладнику, причем не одному, а сразу всем нужно заботиться, чтобы не наступить на такие "грабли"? МетаТрейдер - это платформа. В ней следует единожды поддержать грамотную обработку любых вызовов - и синхронных и асинхронных. В случае вызова любого метода (неважно, что там внутри - обращение к dll или к mql) виртуальная машина должна ждать окончания вызова. Платформа должна позаботиться о том, чтобы прикладник никакими средствами не нарушил её поведение (в частности, стек вызовов, содержимое переменных и памяти). Проще как раз реализовать синхронизацию в платформе.

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

 

Ну это уже философия :) я по этому поводу вообще не парюсь.

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