вопрос по внешним DLL

 
Уважаемые разработчики (а также все, кто знает)!

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

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

Вопросы:
1. Есть ли у кого-нибудь пример, которым он может поделиться, работающего кода, вызываемого индикатором и экспертом, и реализующего эту самую многозадачность? Потому, что предложенный разработчикаим пример, хоть и позволяет обмениваться с DLL отдельными числами, но многозадачности там нет, и что-то мне подсказывает, что и не будет.

2. Кто-нибудь делал это через семафоры в коде MQL, типа
int start()
{
	while(GlobalVariableGet("bBusy") == true)
		Sleep(1); 
	GlobalVariableSet("bBusy", true);

	...
	
	GlobalVariableSet("bBusy", false);
	return(0);
}



Если да, то какой именно (этот код иногда глючит).

С уважением,
Кварк

 
прежде всего пересмотри необходимость подключения своего DLL...
то есть сравни геморрой который ты уже имеешь с результатами которые ты может быть получишь :)
 
первое правило разработчика - сначала цель, а уж потом эргономика
 
2 Quark
DLL имеет достаточно сложную внутреннюю логику, и каждый тик хоть несколько миллисекунд, да работает.
Если у меня эта DLL использутеся из нескольких экспертов (окон), возникают конфликты доступа.


Я достаточно много повозился со связкой МТ - dll, ни о каких конфликтах доступа речь не идет по определению (хотя, если постараться, думаю можно в dll-функции объявить static-переменную, и нарушить логику работы, но это - по желанию). Проверь лучше логику работы функции в dll.

У меня была пара вариантов, когда МТ падал с crash-логом, - несовпадение прототипов функций, и чтение / запись за пределы входных массивов, посмотри, может быть в этом дело.. может, что еще вспомню.. Кроме того, внутренние преобразования int - float - double сильно влияют на точность, но это уже к слову..

2 Andrey
прежде всего пересмотри необходимость подключения своего DLL...
то есть сравни геморрой который ты уже имеешь с результатами которые ты может быть получишь :)

Геморой только в отладке, согласен, зато свобода деятельности какая!! :)
 
Quark,
На каком уровне вам необходимо реализовать многопоточность? с какой целью?
Насколько я вас понял ваша DLL обрабатывает какие-то данные и возвращает результат индикатору. При этом необходимо чтобы данные одного индикатора НЕ перемешивались с данными другого индикатора.
Из этого следует, что в своей DLL вы используете один буфер для вычислений и периодически происходит единовременное обращение к этому буферу, что вызывает конфликт доступа.
Если это так то можно дать следующие рекомендации:

1. Создайте в DLL класс, который будет содержать всю необходимую функциональность, а также свой буфер для вычислений (в качестве члена класса).
2. Создайте внешний набор функций которые обеспечат реентерабельность DLL. Это подразумевает, что есть некоторый набор функций, как-то:
- CreateMyClass - создает экземпляр функционального класса и возвращает его идентификатор.
- DeleteMyClass - удаляет экземпляр по данному идентификатору.
- CalculateMyClass - функция вычисления, для индикатора, который помнит идентификатор экземпляра функционального класса.

Таким образом, вы решите все свои проблемы, с многопоточностью..
 
Если у меня эта DLL использутеся из нескольких экспертов (окон), возникают конфликты доступа.

попробуйте разрешать конфликты доступа хотя бы через критические секции.
настоятельно рекомендую изучить книгу Джеффри Рихтера "Для профессионалов. Windows. Создание эффективных Win32-приложений с учётом специфики 64-разрядной версии Windows" русская редакция Питер. (к сожалению, у меня нет под рукой более старых книг Рихтера - ими тоже можно воспользоваться)
почитайте про синхронизацию потоков - там приведено масса примеров.


2. Кто-нибудь делал это через семафоры в коде MQL, типа
int start()
{
	while(GlobalVariableGet("bBusy") == true)
		Sleep(1); 
	GlobalVariableSet("bBusy", true);

	...
	
	GlobalVariableSet("bBusy", false);
	return(0);
}



Если да, то какой именно (этот код иногда глючит).


этот код не должен глючить. как именно он глючит?
парочку рекомендаций всё же дам:
1. проверяйте условия не на false/true, а на 0/не 0. дело в том, что в глобальных переменных хранятся числа с двойной точностью и Ваши сравнения теоретически могут не сработать.
2. перед return(0) поставьте Sleep(2), чтобы другой эксперт гарантированно получил доступ к глобальной переменной
 
Вопрос разработчикам.

Расскажите пожалуста вкратце как устроена многозадачность в МТ.
Мне показалось (по разным признакам), что МТ это однопоточная система со встроенной внутрь невытесняющей многозадачностью (как оно в Win 3.1 было).

Да и фраза - "перед return(0) поставьте Sleep(2), чтобы другой эксперт гарантированно получил доступ к глобальной переменной" - говорит о том же.

Для написания взаимодействующих экспертов юзерам нужно представлять логику работы МТ.
 
Мне показалось (по разным признакам), что МТ это однопоточная система со встроенной внутрь невытесняющей многозадачностью (как оно в Win 3.1 было).

Не мысль, а просто шедевр! :-)

MT4 конечно же многопоточная программа.
В свою очередь, все программы на MQL4 (кроме индикаторов на чарте) работают в собственных независимых потоках, не тормозя интерфейс программы. Индикаторы, прикрепленные к чартам, пересчитываются в одном потоке по очереди. Индикаторы, вызываемые из экспертов или скриптов, работают в вызываемом потоке.
 
Отвечаю всем.
1. Да, внешняя длл нужна. Если вы предлагаете мне писать нейросети на MQL, то наверное, проще застрелиться, дважды, в голову.
2. Насчет внутренней логики. Не знаю, в чем дело. Ренат мой код видел, и обозвал глючным. В принципе, я согласен, но с тем куском MQL кода, который приведен выше, все пока (тьфу-тьфу) работает и не падает. Без него - работало с предыдущим билдом, не работает с нынешним, и не работало два билда назад. Это, кстати, очень плохой знак, говорящий, что, возможно, дело все-таки в моем коде, а не в МТ.
3. Насчет того, где падает MQL, приведенный выше. После моего поста он падать перестал, и с тех пор (12 часов) не упал ни разу. Наверное, фаза луны влияет.

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

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

Пока что работает вариант с регулированием доступа через глобальные переменные MQL, посмотрим, что будет дальше.
 
Не мысль, а просто шедевр! :-)

Ренат, из вас так и прет ...

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

Вот это я и заметил, об этом и говорил ..

И заодно вот эту рекомендацию не поясните?
парочку рекомендаций всё же дам:
................
2. перед return(0) поставьте Sleep(2), чтобы другой эксперт гарантированно получил доступ к глобальной переменной
 
И заодно вот эту рекомендацию не поясните?
парочку рекомендаций всё же дам:
................
2. перед return(0) поставьте Sleep(2), чтобы другой эксперт гарантированно получил доступ к глобальной переменной

у нас нет атомарных операций блокировки-разблокировки типа EnterCriticalSection или LeaveCriticalSection. и правильное ожидание можно организовать только с использованием функции Sleep (то есть, нет ожидания освобождения ресурсов типа WaitForSingleObject, как нет их блокировки/разблокировки). поэтому Sleep(2) даёт шанс другому процессу (если тот как раз находится в ожидании) взвести семафор.
Причина обращения: