Владимир написал: TGB , Потому что страшно! Перестанет ведь работать и то, что работает, если реализовывать все эти идиотские "пожелания"!
Я думал что вы бесстрашный Вы же можете оставаться на "любимых" вами версиях (даже на QUIK 7....) достаточно долго (минимум, лет 5). Какие у вас проблемы?
Владимир написал: А теперь замените "браузер" на QUIK и перечитайте ещё раз.
У вас такой печальный опыт. У меня была счастливая возможность наблюдать, а иногда и участвовать в том, как качество программ программ, со временем, улучшалось. Надеюсь что и вам, если вы будете переходить на новые версии QUIK, выпадет (через год?) такое счастье . А чтобы ощутить это сейчас, вы могли бы перейти на QUiK 8.5, а потом вернуться на версию, которую используете сейчас.
Владимир написал: А если nikolz писал то же самое, то а данном случае я с ним согласен.
Декларация вашего мнения в данной ситуации не очень существенна. Оно уже многократно вами озвучено и старо как этот мир: не пущать Но жизнь не остановить. Будут новые версии QUIK. Будут в нем ошибки и исправления. Странно то, что вы с этим продолжаете безнадежно бороться. Вы что, жизни не видели?
nikolz написал: VMLua - никакого отношения к КВИКУ не имеет.
Ну и как вы объясните 16-ти кратную разницу времени выполнения скрипта ?: 1) В QUIK 8.13.1.16 (QLua 5.4) T = 0,00016 ; 2) В QUIK 9.3.1.11 (QLua 5.4) T = 0,0026 ??? (в 16,25 раз дольше) -----
Вам не лень всякий раз цитировать комментарии пользователей полностью? Не можете удержаться перед халявой? Вы же так можете разорить АРКУ на накопителях базы форума
Владимир написал: просьба: отвяжитесь от разработчиков, не заставляйте их гробить софт реализацией своих идиотских пожеланий
Я бы на месте АРКИ зачислил вас в нештатные сотрудники --- 2. Конечно, при разработке скриптов желательно чтобы они были (выполняя свои функции) как можно проще и допускали простоту последующей модификации. Рыночная эффективность торговой стратегии (ее доходность на определенном перио-де) может не сильно коррелировать с ее сложностью. Поэтому при разработке скрипта имеет смысл начинать с простых стратегий, не требующих много данных и вычислений и только потом добавлять учет дополнительных факторов поведения рынка. QUIK не то место, в котором надо заниматься событийным программированием, существенно усложняющим скрипты. Колбеки следует использовать по минимуму. Лучше от-слеживать доступные в QLua состояния рынка, а также состояния выполнения заявок. Заявки лучше использовать только лимитированные, иначе будут возникать рыночные по неконтролируемым ценам. Все сложные заявки системы: со стопами, тейки, айзберги и т.д., если вдруг они требуются, лучше реализовать в самом скрипте с использованием комбинаций лимитированных заявок. Собственные сложные заявки, будут выполняться с некоторой задержкой по времени (по сравнению с системными), во многом определяемой качеством канала связи с вашим брокером, но за это вы будете иметь более полный контроль над ними. ---- 3.
Цитата
Владимир написал: TGB , Нет никакой "проблемы производительности скриптов в QUIK".
Во втором пункте я написал, что скрипты желательно создавать простыми, Но это вовсе не означает, что инструмент для их создания должен быть «корявым». И когда после очередного изменения QUIK, создание таблиц в OLua начинает выполняться в 16 раз дольше, чем до изменения, то это оскорбляет «мои эстетические чуства» . Вы понимаете, что в QLua фактически единственный тип это таблица с индексами/ключами и полями (известных типов)? Замедление в 16 раз это аномальное поведение QLua, с которым должны были разобраться разработчики QUIK. Что они и сделали, выпустив версию QUIK 9.3.3.3, в которой этого замедления нет. Это не значит, что в этой версии нет проблем, о которых написали другие пользователи (это надо проверять). То, что в QUIK возникают и исправляются ошибки это нормально. Главное это чтобы исправленных было больше чем возникших. Плохо то, что поддержка не дает четкого объяснения возникающих ситуаций. ---- Для того чтобы не разбираться с новыми глюками новых версий QUIK, у вас есть воз-можность выбрать существующую версию с «любимыми» вами глюками и оставаться на ней столько, сколько вам захочется.
nikolz написал: попробуйте исполнить Ваш тест вне квика и сравните время исполнения.
Предложение почти гениальное, особенно с учетом того, что обуждается проблема производительности скриптов в QUIK У вас нет понимания, что при встраивании Lua в QUIK его разработчиком вносятся изменения, которые способны изменить встроенного Lua?
Цитата
nikolz написал: Дело в том, что в ваш пример некорректный.0.00016 это 160 us0.0026 это 2.6 ms
Переведите все в терасекунды и вам все станет понятнее
Владимир написал: И если СОЗДАНИЕ таблиц вдруг замедлится в 16,25 раз, меня это НИСКОЛЬКО не обеспокоит.
Я понимаю, что вы "крутой" и вам от Qlua почти ничего не нужно. Но у меня есть друг, кстати, программист, торгующий довольно успешно вручную, а потому бесконечно круче вас
Владимир написал: Ну, выполняется эта хрень в 16,25 раз дольше чем в QUIK 8.13.1.16 - и чего?
А того, что некоторые пользователи достаточно активно используют таблицы Lua (это относится и ко мне) и все, что связано с созданием таблиц, в QUIK 9.3.1.11 (QLua 5.4) выполняется в 16,25 раз дольше чем в QUIK 8.13.1.16 (QLua 5.4). Это влезли в ваш ПК и снизили его производительность в 16 раз. Я не понял, что вы так заботитесь о том, чтобы разработчик QUIK не устранял глюки? Если у вас все хорошо, зачем вы мешаете другим пользователям решать свои (а может быть и ваши) проблемы?
Владимир написал: На месте техподдержки я бы то же самое сказал и о приведенном коде. Ну, выполняется эта хрень в 16,25 раз дольше чем в QUIK 8.13.1.16 - и чего? Самое разумное - отправить весь код на помойку, не читая.
Я бы папуасам не рискнул объяснять, что такое тензорное исчисление, но у меня есть надежда, что поддержка не папуасы ---- Вообще то, новые версии QLua у разработчика QUIK должны проходить хотя бы простейшие тесты. Например, без подключения к серверу: 1) проверка подключения пакетов; 2) проверка скорости выполнения циклических операций; 3) проверка работа таблиц: - скорости создания таблиц; - скорости доступа к элементов И так далее …… ---- Неужели этого у разработчика QUIK до сих пор нет таких тестов?
В ниже приведенном коде выделена строка символами ###, которая в QUIK 9.3.1.11 (QLua 5.4) выполняется в 16,25 раз дольше чем в QUIK 8.13.1.16 (QLua 5.4) Где поддержка??
Код
--- Загрузка CPU ---
IsRun = true
function main()
local T
local hour = 0, N
N = 1000000
-------------------
while IsRun do
T = os.clock()
for i = 1, N do hour = {} end
T = (os.clock() -T) * 1000 / N ---- ### !! Без подключения к серверу: 1) В QUIK 8.13.1.16 (QLua 5.4) T = 0,00016 ;
--- 2) В QUIK 9.3.1.11 (QLua 5.4) T = 0,0026 ??? (в 16,25 раз дольше)
message (tostring(T))
sleep(500)
end
------------------
end
function OnStop()
IsRun = false
return 10000
end
_sk_ написал: Думаю, что очень актуальный вопрос поднят. Спасибо топик-стартеру за демонстрацию проблемы. От разработчиков терминала ждём пояснений.
Присоеденяюсь. ----- Деградация эффективности QLua показатель низкого качества реализации разработчиками QUIK встраивания Lua в QUIK. Эффективность выполнения скриптов QLua без обращения к API QUIK должна отличаться от Lua только затратами на операции lock/unlock в вызовах функций C-API QLua, а также в VM-QLua (ulock/lock) при вызове C-функций. Причем упомянутые операции в подавляющих случаях «холостые» (потоки не переключают). Все места вызова lock/unlock (ulock/lock) определены в кодах Lua разработчиком Lua. Разработчику QUIK достаточно корректно реализовать lock/unlock, например, используя критические секции, обеспечивающие эффективную синхронизацию. Вопрос к поддержке: какое «ноу-хау» обеспечивает деградацию эффективности QLua новых версий? -----
Цитата
Anton написал: Сложился паззл. Когда в девятой версии смотрел "чего нового" в отладчике, увидел, что после каждого колбека lua_gc добавили.
Интересное открытие (пишу без иронии). Вопрос к поддержке: a это зачем сделали? Хотелось бы чтобы разработчик QUIK пояснил как додумался до этого. Какие проблемы это решает?
Старатель написал: QUIK 9.3.1.11, Lua 5.4Ещё парочка "неуловимых" косяков. Обе ошибки были в main. Никаких сторонних библиотек не подключено, только QLua-код.
Итак, в Qlua 5.4 есть «плавающая» ошибка (скорее всего ошибка синхронизации). --- «Простой» тест, диагностирующий некорректную обработку колбеков в QLua 5.3, появился у меня в результате анализа «мерцающей» ошибки в скрипте, похожей на ошибки в QLua 5.4, описанные Старателем, когда в переменной сразу после присвоения ей значения, это значение на следующем шаге оказывалось искаженным. Нельзя исключать, что природа ошибок, обнаруженных Старателем и мною одна и та же. Притом, что обсуждаемый тест ошибку в QLua 5.4 не показывает на коротком интервале времени, это совсем не значит, что такой ошибки в QLua 5.4 нет. Дело в том, что проявление ошибок синхронизации по времени может сильно зависеть и от того какая версия QLua используется. Я могу ошибаться, но, скорее всего, схемы синхронизации потоков в QLua 5.3 и в QLua 5.4 аналогичны. Поэтому, если бы разработчик QUIK, нашел бы ошибку в QLua 5.3, то он бы, наверное, нашел бы ее и в QLua 5.4. Обсуждаемый тест воспроизводит ошибку (в описанных мною условиях) в QLua 5.3 в интервале 2-3 мин. с локализацией места с точностью одной строки кода.
Alexey Ivannikov написал: Добрый день.Результат разбора был передан Вам в сообщении 84 (выше). Если Вы не согласны с данной резолюцией - просьба подробно описать почему, мы передадим эту информацию разработчикам.
Здравствуйте. Действительно, обсуждаемую ошибку в QLua 5.4 я не наблюдал. Но, если разработчик QUIK поддерживает и QLua 5.3, то, наверное, надо эту ошибку устранить и в QLua 5.3. Тем более, что эта ошибка базовой функциональности обработки колбеков. Причем, тест https://forum.quik.ru/messages/forum10/message58500/topic5823/#message58500 , диагностирующий ошибку мною упрощен до такой степени, что проявление ошибки в коде теста локализовано в пределах одной строки, помеченной комментарием --- ###. Этот тест разработчик может использовать при поиске ошибки в QLua. Просьба передать его коды и описание ошибки в комментарии https://forum.quik.ru/messages/forum10/message57872/topic5823/#message57872 разработчику QUIK.
В предыдущем моем комментарии у меня не было времени подробно пояснить, что понимается под схемой использования Lua во многих потоках. Попробую это сделать сейчас. Главный thread и остальные thread Lua пространственно, по стеку, разделены и поэтому могли бы обрабатываться в разных потоках без синхронизации. Но не допустима обработка любого thread в нескольких потоках. Если в разных thread нет общих модифицируемых данных, то синхронизация между thread не требовалась бы. Казалось бы, thread могли бы работать параллельно, синхронизируясь только на общих модифицируемых данных. Однако, в Lua есть «общее хозяйство» всех thread , требующее синхронизацию – это общая автоматическая память Lua, поддерживаемая мусорщиком, «заточенным» разработчиками Lua только на однопоточное использование. Поэтому VM-Lua можно использовать в разных потоках только в разделяемом режиме. В любой момент времени VM-Lua может обрабатывать только один поток.
Anton написал: В общем случае в 5.3 замыкание может создаваться небезопасно
При корректной синхронизации (в тех местах кода Lua, определенных разработчиком Lua) в той схеме, которую определили разработчики Lua для использования ее во многих потоках, почему? Не понял. В этой схеме работа Lua эквивалентна ее однопоточному использованию. Я это проверял и пока ошибок у разработчиков Lua не обнаружил.
Alexey Ivannikov написал: Поведение Lua 5.4 считаем правильным, т.е. именно таким, каким было задумано её автором, и рекомендуем использовать именно её.
Здравствуйте. Действительно, обсуждаемую ошибку в QLua 5.4 я не наблюдал. Но, если разработчик QUIK поддерживает и QLua 5.3, то, наверное, надо эту ошибку устранить и в QLua 5.3. Тем более, что эта ошибка базовой функциональности обработки колбеков. Причем, тест https://forum.quik.ru/messages/forum10/message58500/topic5823/#message58500 , диагностирующий ошибку мною упрощен до такой степени, что проявление ошибки в коде теста локализовано в пределах одной строки, помеченной комментарием --- ###.
Я поддерживаю поддержку QUIK в стремлении навести порядок на форуме. Здесь не подворотня. «Стычки» между пользователями, конечно, допустимы (в профессиональных рамках), но без перехода на личности. Как мне представляется, «грязный» спам, не имеющий отношение к обсуждаемой теме, поддержка может удалять исходя из своих представлений без объяснения своих мотивов. Миндальничать, наверное, не надо.
local for_OnParam = 2 -- Множитель
local N_OnParam = 0
----
function OnParam(p1, p2)
for i = 1, for_OnParam do
N_OnParam = N_OnParam + 1
end
end
---
--------
IsRun = true
function main()
local J
local OnParam_begin
-------------------
while IsRun do
------
do
OnParam_begin = N_OnParam
J = 100000000
while ( J > 0 ) do J = J - 1 end -- ### Проблема здесь. "Чистый" байт-код, но в QLua 5.3 здесь переключаются потоки (! в 5.4 этого нет)----
-- for i = 1, 100000000 do end -- Это в QLua 5.3 работает нормально ---
if N_OnParam ~= OnParam_begin then -- Счетчик N_OnParam может исмениться только в OnParam
message ( ' Переключение колбека и потока main: N_OnParam - OnParam_begin = ' .. tostring(N_OnParam - OnParam_begin))
end
end
-----
sleep(10)
end
------------------
end
function OnStop()
IsRun = false
return 10000
end
Anton написал: Соответственно причина явно не в этом.
Согласен. luaL_setfuncs не применима к функциям Lua, а только к С-функциям. --- Эксперименты показали, что проблема в lua_pcall (нет блокировки доступа к байт-кодам). Либо в этой функции нет синхронизации в QLua 5.3 (что очень сомнительно), либо в ней не корректно указана ссылка на объект синхронизации (он должен быть общим для всех lua_State скрипта).
Anton написал: Этот параметр указывает количество upvalues, прицепленных к каждой функции. Их можно и к сишным функциям прицепить. Соответственно причина явно не в этом.
Вообще, мне (и остальным пользователям QUIK) не интересны причины наблюдаемой ошибки. Нам существенно, чтобы эта ошибка была устранена.
Daniil Pozdnyakov написал: Проблема, о которой Вы говорите, на данный момент изучается, и, к сожалению, какую-либо резолюцию, а также сроки решения данной задачи дать не можем.
Долго изучаете проблему. Не точно, но скорее всего, колбеки регистрируются в QLua (а этого можно и не делать - смотрите мои комментарии) с помощью функции: void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) и, наверное, с параметром nup = 0. Параметр nup = 0 означает, что это C - функции и они запускаются без блокировки байт-кодов. Что является ошибкой. ---- Возможно, я ошибаюсь, и все-таки просьба к поддержке: донести этот комментарий до разработчиков QUIK.
Зачем смуту сеете в «неокрепшие» умы ? --- Даже если ядро одно, то все равно может сброситься. Потоки и при одном ядре переключаются по времени из-за выделения им квантов процессорного времени. Переключение на выполнение потока колбека может случиться сразу после проверки в main: os.time () > Time. И тогда Time может сброситься при выполнении колбека.
Daniil Pozdnyakov написал: Ваше письмо получено, проблема изучается. Постараемся в ближайшее время дать ответ.
Здравствуйте! Появилась версия QUIK 9.2.2.11 (с обновлениями). В этой версии в QLua 5.3 тест, описанный в комментарии (10.09.2021) https://forum.quik.ru/messages/forum10/message57872/topic5823/#message57872 демонстрирует ошибку в запусках колбеков. Эта ошибка может проявляться как случайные сбои в сриптах пользователей в различные моменты времени. В версии в QLua 5.4 ошибка не проявляется У поддержки есть вопросы по тесту?
1. nikolz зачем при ссылке на мой код процитировали его весь? Он все-таки длинный и достаточно было бы привести несколько строк. У вас что, есть план по объему генерации текстов своих комментариев ? 2. Это
вы написали не случайно ? А если так, то можно предположить, что это разрешение вашего гипотетического таймера, который вы собираетесь создать (готового пока у вас я не вижу ничего) используя
Цитата
nikolz написал: пул событий на основе WaitForMultipleObjects.
Разрешение таймера в 0.1 мкс в Windows (только не путайте с возможностью засечки времени в Windows с использованием QueryPerformanceCounter) было бы круто не только для QLua, но и для C. Я, правда, не очень понимаю, зачем такое разрешение нужно в QLua, но ваша заява так впечатляет и претендует на открытие, что мне стало интересно, а вдруг вы Кулибин от программирования . Вам известно, что интервалы в WaitForMultipleObjects можно задать только в млсек.? Вообще, расскажите подробно в деталях, что вам известно о WaitForMultipleObjects (возможно, неизвестное мне), позволяющее, по-вашему, мнению, использовать эту функцию для обеспечения разрешения вашего гипотетического таймера в 0.1 мкс. Только не рассказывайте, это на «растопыренных» пальцах, а приведите нормальное API и к нему нормальный код (лучше, ваш, работающий, или хотя бы, найденный в сети) на каком-нибудь, известном вам языке программирования. Я попытаюсь такой код понять и как то его прокомментировать.
nikolz написал: Реализовал это, создав пул событий на основе WaitForMultipleObjects. В итоге бесконечный цикл запускается через заданный в функции ожидания интервал,т е это тайме собаки,либо при срабатывании любого колбека QLUA или любой функции пользователя, для которой описано событие. При возникновении события запускается соответствующий ему колбек. Количество событий- любое. Количество колбеков- любое. Все события контролируются OC. Примерно так.
И это весь ваш (очень простой ) работающий код, который я могу запустить на своем ПК с тем, чтобы проверить, как он замечательно работает? --
Ну, если бы приведенный вами «код» работал бы, то это было бы, конечно, большое достижение, особенно с учетом того, что все исполняемые приложения контролируются ОС .
По ссылке https://cloud.mail.ru/public/ts3g/4PJofyayZ расположены коды для работы из QLua (5.3, 5.4) c базами SQLite. !! Файл sqlite3.dll одинаковый для 5.3 и 5.4. Простой вариант подключения к пакету: 1) Переслать файлы варианта 5.3, либо 5.4 в папку с info.exe 2) В скрипте подключиться к пакету следующим образом
Код
local WorkingFolder = getWorkingFolder()
package.cpath = package.cpath .. ';' .. WorkingFolder .. '\\?3.dll' -- C - пакеты ----
sqlite3 = require('lsqlite3'); ------ Подключение пакета работы с sqlite3 -----
---- Далее использовать функции работы с базами: sqlite3.<Функция работы с базами>
При таком подключении можно использовать коды только либо для Lua 5.3, либо для Lua 5.4. Сделать автоматический выбор пакетов в зависимости от того как запускается скрипт (Lua 5.3 или Lua 5.4) несложно.
nikolz написал: Попробуйте использовать таймеры ожидания (таймеры ядра)Такое решение и проще и лучше. Не надо создавать новые потоки.Квант таймера 0.1 мкс.Программирование гораздо проще, чем ваша скатерть-самобранка.
Ну. про это я, наверное, знаю. А вы попробуйте привести здесь свой работающий код и тогда поговорим.
2. Тот кто соображает, поймет, что выложенный мною модуль обеспечивает возможность запускать пользователю свои функции в отдельном (от основного потока QUIK) потоке.
Нужно ли переносить функциональность скрипта в основной поток с учетом написанного мною в предыдущем комментарии, а также с учетом цитируемого ниже?
Цитата
TGB написал: Таблицы обслуживаются только в одном основном потоке. Доступ к данным - тоже только в одном потоке.Так что все ваши "несколько скриптов" дружно встают в очередь, как только им понадобится что-то вывести в таблицу. И включаются в общую конкурсную массу вмести с другими таблицами и графиками.
Ответ разработчика QUIK (документ «Использование Lua в Рабочем месте QUIK»): «При использовании событийной модели Lua скрипт выполняется в двух потоках: функции обратного вызова выполняются в основном потоке РМ QUIK, а функция main() в до-полнительном потоке РМ QUIK (подробнее см. п. 1). При этом для предотвращения «подвисаний» РМ QUIK необходимо каким-либо образом оптимизировать сценарии, описан-ные в функциях обратного вызова. Одним из способов такой оптимизации является перенос логики обработки полученных сигналов в функцию main(). Данный подход сводит количество сценариев в функции обратного вызова до одного, а именно добавление в глобальную Lua таблицу (очередь) записи о том, что функция сработала и вернула определённые значения. Таким образом, мы получаем очередь событий, которые необходимо обработать в другом потоке.» ----- Если кому интересно, то в моем комментарии https://forum.quik.ru/messages/forum10/message57686/topic6198/#message57686 выложен код реализации модуля обработки событий колбеков и событий таблиц QUIK с использованием очередей. Там же приведен скрипт-шаблон подключения модуля и при-мер его использования. При использовании очередей проблем синхронизации нет вообще. Основной поток выполняет по событиям QUIK только короткие записи параметров колбеков в очереди, которые обрабатываются в потоке main.
Старатель написал: Цитата TGB написал: перенос коротких задач пользователя в колбеки делает скрипт пользователя многопоточным, то есть, при этом пользователю нужно следить за тем, нет ли в его скрипте проблем синхронизации.
В данной ветке, наоборот, обсуждение, переноса задачи, выполняемой по таймеру, в основной поток, чтобы не заморачиваться синхронизацией: Цитата _sk_ написал: удобно иметь возможность инициировать какой-то коллбэк из потока main, не надо думать про синхронизацию
Из выше приведенного я понял, что о синхронизации мною было написано слишком лапидарно и не очень понятно. Попробую пояснить это более детально. Проблемы синхронизации возникают, только в случае, если у двух или более потоков есть общие модифицируемые при обработке данные. Поэтому при обработке колбеков, до тех пор, пока в main есть только цикл со sleep, то синхронизацией можно не озадачиваться. Но как только, после очередного внесения изменений в скрип, появятся общие для функций колбеков и функций main модифицируемые данные, с синхронизацией следует разбираться. Причем, проблемы синхронизации возникают не в отдельных потоках, а при их взаимодействии. Конечно, можно всю функциональность скрипта перенести в основной (единственный) поток QUIK и не будет никаких проблем с синхронизацией. Надо только следить за тем, чтобы при изменении скрипта не появились общие (для main и основного потокаQUIK) модифицируемые данные.
Старатель написал: TGB , в одном месте вы пишите , что байт-код не должен прерываться, в другом наоборот. Вас двое что ли?
Не надо комплиментов насчет того, что я могу заменить двоих . Нужно все-таки отличать настоящее и будущее. Вы что. не понимаете разницу между настоящим и будущим? Или притворяетесь? В настоящем байт-код в QLua не должен прерываться (так это сейчас "коряво" реализовано), а я пишу о "светлом" будущем, когда длинные участки участки непрерывного байт-кода не должны блокировать друг друга. Когда вы работаете в любой операционной системе на ПК с одним одним ядром ЦП, то при том что ядро одно, выполнение нескольких приложений в этих ОС не блокируют друг друга, а получают свой кванты ЦП. Про это вам известно?
Roman Azarov написал: TGB , добрый день! Оба пожелания зарегистрированы, мы постараемся их рассмотреть. Впоследствии, по результатам анализа, будет приниматься решение о реализации пожеланий в будущих версиях ПО. Каких-либо сроков назвать не можем. Как будет результат анализа пожеланий, мы сообщим Вам в данной теме.
Сегодя 23.09.21. С тех пор прошло более четырех месяцев. Где результат рассмотрения? Просьба к поддержке: сообщить результат рассмотрения первого пожелания (изложенного мною, с протестированным вариантом его реализации в виде конкретного кода), устраняющего блокировку потоков длинными участками байт-кода. У вас есть замечания относительно предложенного мною кода? Я готов дать развернутый комментарий. ---- !! Второе пожелание факультатив и, наверное, его не стоит реализовывать. Оно не устраняет ошибок в QLua, достаточно сложное в реализации для разработчиков QUIK (и при некорректной реализации может внести ошибки в QLua) и, наверное, не актуально для большинства пользователей QUIK.
_sk_ написал: Добавить функцию обратного вызова OnTimer(), которая будет вызываться терминалом с некоторой периодичностью
В данном комментарии выложен модуль работы с таймерными событиями в отдельном потоке и шаблон его использования. ---- API работы с таймерными событиями: 1) Start_Timer() - запуск отдельного потока обработки таймерных событий. 2) <Ключ события> = Set_Timer ( {<Имя события>, <Интервал в млсек.>, <Функция обработки события>,{<Список парвметров функции>}} ) - запрос таймерного события. Через <Интервал в млсек.> будет запущена в отдельном потоке <Функция обработки события> со <Списоком парвметров функции>. 3) delete_Timer (<Ключ события>) – удаление при необходимости запрошенного собы-тия. ---- Модуль и две dll (service53.dll и service54.dll) , скачанные по ссылке: https://cloud.mail.ru/public/i3Y7/kQHBvs7um необходимо положить в папку хранения info.exe. --- Модуль OnTimer (для QLua 5.3 и 5.4):
Код
-- Модуль таймерных событий OnTimer ---
-- Подключение C-пакетов service53, service54: https://cloud.mail.ru/public/i3Y7/kQHBvs7um
local WorkingFolder = getWorkingFolder()
package.cpath = package.cpath .. ';' .. WorkingFolder .. '\\?.dll' .. ';' .. WorkingFolder .. '\\?53.dll'.. ';' .. WorkingFolder .. '\\?54.dll' .. ';' .. WorkingFolder .. '\\?51.dll'
.. ';' .. WorkingFolder .. '\\?3.dll' -- C - пакеты ----
if _VERSION == 'Lua 5.3' then
require('service53') -- Подключает библиотеку service.dll, расположенную в корневом каталоге терминала QUIK (там где info.exe) ----
else
require('service54')
end
local GetMilliseconds, Start_thread = service.GetMilliseconds, service.Start_thread
--- Функции работы с очередями ---
local new = function ()
return {first = 1 , last = 0 }
end
---
local push = function (self, v)
local last = self.last + 1
self[last] = v
self.last = last
return last
end
---
local pop = function (self)
local first = self.first
if first > self.last then return nil end
local v = self [first]
self.first = first + 1
self[first] = nil
return v, first
end
--------- Создание очереди ------
local Queue_Timer = new() --- Таймерные события -----
local Queue_Timer_Sl = new() --- Очередь отмены событий ---
-------------------------------------------
--- Заказ таймерных событий ----
--- Таймерное событие: {<Имя события>, <Интервал в млсек.>, <Функция обработки события>,{<Список парвметров функции>}}
local function Set_Timer (self)
if type(self) == 'table' then
if #self >= 3 then
self [2] = self [2] + GetMilliseconds()
return push (Queue_Timer, self)
else
message ( '!!! Ошибка. Должно быть: {<Имя события>, <Интервал в млсек.>, <Функция обработки события>,{<Список парвметров функции>}}')
end
else
message ( '!!! Ошибка (параметр не таблица). Должно быть: {<Имя события>, <Интервал в млсек.>, <Функция обработки события>,{<Список парвметров функции>}}')
end
end
-----
local function delete_Timer (kl)
push (Queue_Timer_Sl, kl)
end
------
local function Timer ()
local ms, first_q
while IsRun do
--- Обработка удалений событий ---
ms, first_q = pop (Queue_Timer_Sl)
while ms do
if Queue_Timer [ms] then Queue_Timer [ms] = nil end
ms, first_q = pop (Queue_Timer_Sl)
end
--- Чтение очереди заказанных событий[ -----
for k, v in next, Queue_Timer do
if type(k) == 'number' then
if v [2] <= GetMilliseconds() then
Queue_Timer [k] = nil
if v[4] then
pcall ( v[3], table.unpack (v[4]))
else
pcall ( v[3]) -- функция без параметров ---
end
end
end
end
-------------------------------------------------------
sleep(2)
end
end
---------------------------------------
local function Start_Timer ()
Start_thread (Timer)
end
------
return {Set_Timer = Set_Timer, delete_Timer = delete_Timer, Start_Timer = Start_Timer }
---------------------------------------------
Шаблон использования модуля:
Код
-- Шаблон использования модуля таймерных событий
local OnTi mer = require('OnTimer') -- Подключение модуля обработки таймерных событий ---
local Set_Timer = OnTimer.Set_Timer
local delete_Timer = OnTimer.delete_Timer
local Start_Timer = OnTimer.Start_Timer
IsRun = true
local function call_Timer (kl)
message ( 'call_Timer = ' .. kl)
end
local function call_Timer1 ()
message ( 'call_Timer1 () ==============')
end
function main()
Start_Timer()
local kl
--- Заказ таймерных событий ----
--- Таймерное событие: {<Имя события>, <Интервал в млсек.>, <Функция обработки события>,{<Список парвметров функции>}}
kl = Set_Timer({'Set_Timer', 100, call_Timer, {100}})
kl = Set_Timer({'Set_Timer', 1000, call_Timer, {1000}})
kl = Set_Timer({'Set_Timer', 5000, call_Timer, {5000}})
kl = Set_Timer({'Set_Timer', 3000, call_Timer1})
-- delete_Timer (kl)
-------------------
while IsRun do
---- Обработка в main остального -----
kl = Set_Timer({'Set_Timer', 1000, call_Timer, {1000}})
delete_Timer (kl)
---- Конец Обработка в main остального -----
sleep(500)
end
------------------
end
function OnStop()
IsRun = false
DestroyTable(TableQUIK)
DestroyTable(TableQUIK1)
return 10000 -- !! По истечении этого интервала времени (в млсек.), данного скрипту на завершение работы, функция main() завершается принудительно.
-- При этом возможна потеря системных ресурсов. ! Если функция не выдает значение, то по умолчанию оно 5000 (5 сек.)
end