Работа OnClose

Страницы: 1
RSS
Работа OnClose
 
Есть колбек OnClose. Казалось бы, он должен помочь понять, что терминал остановлен. Но явно что-то пошло не так.

Берем простой скрипт. Закрываем терминал через "крестик".

Ожидание - 1. OnClose, сбрасываем флаг. 2. выходим из main.
Код
local sleep  = _G.sleep
local isRun  = true
local AddLabel          = _G.AddLabel
local GetLabelParams    = _G.GetLabelParams
local logFile

local function log_tostring(...)
    local n = select('#', ...)
    if n == 1 then
    return tostring(select(1, ...))
    end
    local t = {}
    for i = 1, n do
    t[#t + 1] = tostring((select(i, ...)))
    end
    return table.concat(t, " ")
end

local function log(...)
    if logFile==nil then return end
    logFile:write(tostring(os.date("%c",os.time())).." "..log_tostring(...).."\n");
    logFile:flush();
end

function _G.OnStop()
    isRun = false
    log("Script Stoped")
    if logFile then logFile:close() end
end

function _G.OnClose()
    isRun = false
    log("Script OnClose")
    if logFile then logFile:close() end
end

function _G.main()

    logFile = io.open(_G.getScriptPath().."\\labels_test.txt", "w")

    local t_id = _G.AllocTable()
    _G.AddColumn(t_id, 1, 'test', true, _G.QTABLE_STRING_TYPE, 20)
    _G.CreateWindow(t_id)

    local tag = 'virt_test'
    local label_params = {}
    label_params.YVALUE = 324
    label_params.TEXT = 'TEST    |||||||||||||||||||||||||||||||||||||||||||||'
    label_params.HINT = 'Еще текст'
    label_params.DATE = 20260512
    label_params.TIME = 135000
    label_params.FONT_FACE_NAME = 'Arial'
    label_params.ALIGNMENT = 'RIGHT'
    label_params.FONT_HEIGHT    = 10
    label_params.TRANSPARENT_BACKGROUND    = 1
    local data = {price = 324}
    local l_id = AddLabel(tag, label_params)
    sleep(1000)
    
    while isRun do
        local i = 1
        while isRun and i < 10 do
            label_params = GetLabelParams(tag, l_id)
            if label_params then
                data.price = tonumber(label_params.yvalue) or 0
            end
            log(os.clock(), i, 'IsWindowClosed', tostring(_G.IsWindowClosed(t_id)), 'label_params', tostring(label_params), tag, 'l_id', l_id, tostring(data.price))
            i = i+1
        end
        log(os.clock(), 'sleep')
        sleep(100)
    end
end

Выводит метку на график, создаём окно. Далее выводим данные метки с графика и закрыто ли окно. Смотрим лог:

Tue May 12 15:07:59 2026 30.832 sleep
Tue May 12 15:07:59 2026 30.946 1 IsWindowClosed false label_params table: 00000205F30168A0 virt_test l_id 13.0 324.0
Tue May 12 15:07:59 2026 30.947 2 IsWindowClosed false label_params table: 00000205F3016BA0 virt_test l_id 13.0 324.0
Tue May 12 15:07:59 2026 30.947 3 IsWindowClosed false label_params table: 00000205F3017BA0 virt_test l_id 13.0 324.0
Tue May 12 15:07:59 2026 30.947 4 IsWindowClosed false label_params table: 00000205F3017160 virt_test l_id 13.0 324.0
Tue May 12 15:07:59 2026 30.947 5 IsWindowClosed false label_params table: 00000205F3018020 virt_test l_id 13.0 324.0
Tue May 12 15:07:59 2026 30.947 6 IsWindowClosed false label_params table: 00000205F30171A0 virt_test l_id 13.0 324.0
Tue May 12 15:07:59 2026 30.947 7 IsWindowClosed false label_params table: 00000205F30171E0 virt_test l_id 13.0 324.0
Tue May 12 15:07:59 2026 30.947 8 IsWindowClosed false label_params table: 00000205F3017F20 virt_test l_id 13.0 324.0
Tue May 12 15:07:59 2026 30.948 9 IsWindowClosed false label_params table: 00000205F3017A60 virt_test l_id 13.0 324.0
Tue May 12 15:07:59 2026 30.948 sleep

Окно ещё не уничтожено, но графика уже нет и данные метки не получены.
Tue May 12 15:07:59 2026 31.061 1 IsWindowClosed false label_params nil virt_test l_id 13.0 324.0
Tue May 12 15:07:59 2026 31.061 2 IsWindowClosed false label_params nil virt_test l_id 13.0 324.0
Tue May 12 15:07:59 2026 31.061 3 IsWindowClosed false label_params nil virt_test l_id 13.0 324.0
Tue May 12 15:07:59 2026 31.061 4 IsWindowClosed false label_params nil virt_test l_id 13.0 324.0
Tue May 12 15:07:59 2026 31.061 5 IsWindowClosed false label_params nil virt_test l_id 13.0 324.0
Tue May 12 15:07:59 2026 31.061 6 IsWindowClosed false label_params nil virt_test l_id 13.0 324.0
Tue May 12 15:07:59 2026 31.061 7 IsWindowClosed false label_params nil virt_test l_id 13.0 324.0
Tue May 12 15:07:59 2026 31.061 8 IsWindowClosed false label_params nil virt_test l_id 13.0 324.0
Tue May 12 15:07:59 2026 31.061 9 IsWindowClosed false label_params nil virt_test l_id 13.0 324.0
Tue May 12 15:07:59 2026 31.061 sleep

А здесь уже и окна нет
Tue May 12 15:08:00 2026 31.173 1 IsWindowClosed true label_params nil virt_test l_id 13.0 324.0
Tue May 12 15:08:00 2026 31.173 2 IsWindowClosed true label_params nil virt_test l_id 13.0 324.0
Tue May 12 15:08:00 2026 31.173 3 IsWindowClosed true label_params nil virt_test l_id 13.0 324.0
Tue May 12 15:08:00 2026 31.173 4 IsWindowClosed true label_params nil virt_test l_id 13.0 324.0
Tue May 12 15:08:00 2026 31.173 5 IsWindowClosed true label_params nil virt_test l_id 13.0 324.0
Tue May 12 15:08:00 2026 31.173 6 IsWindowClosed true label_params nil virt_test l_id 13.0 324.0
Tue May 12 15:08:00 2026 31.173 7 IsWindowClosed true label_params nil virt_test l_id 13.0 324.0
Tue May 12 15:08:00 2026 31.173 8 IsWindowClosed true label_params nil virt_test l_id 13.0 324.0
Tue May 12 15:08:00 2026 31.173 9 IsWindowClosed true label_params nil virt_test l_id 13.0 324.0
Tue May 12 15:08:00 2026 31.173 sleep

Только сейчас OnClose
Tue May 12 15:08:00 2026 Script OnClose

Сама по себе схема, вроде, корректна, если бы OnClose мог выполнится параллельно, не обращая внимания на работу main. Но это не так. В итоге OnClose вызывается когда уже уничтожено окно скрипта и нет графика. Т.е. некоторое время (а точнее пока не вызовется C функция) у нас есть подвешенное состояние - мы не знаем окно, график закрыты пользователем или нет.
В итоге, если в это время считаем метку, а её нет, можем принять не верное решение. Аналогично и по окну скрипта.

Что хотелось бы: вместо колбека иметь глобальный флаг, состояние или иное, сигнализирующее, что терминал закрывается. При этом он должен быть установлен быстро, перед уничтожением объектов терминала. Аналогия из электротехники - логическое 1 или 0 на контакте. Если 0, то уже всё, логика работы совершенно иная.

Текущая же реализация может работать, если бы OnClose вызывался до уничтожения объектов.
 
до кучи...
В документации сказано:
Код
OnClose

Функция вызывается перед закрытием терминала QUIK и при выгрузке файла 
qlua.dll. 
Формат вызова: 
OnClose()


Под выгрузкой файла qlua.dll подразумевается отключение плагина QLua в окне 
«Версии компонентов и плагинов» (см. п. 1.9. Раздела 1 Руководства пользователя 
QUIK).
Но если  работает несколько скриптов,
то файл qlua.dll , если это dll ,
не будет выгружаться,
если есть хотя один работающий скрипт.
-----------------------  
Таким образом, этот колбек вызывается либо коггда терминал закрывается,
либо когда останавливается последний скрипт.
что не так?
 
 
Добрый день.

Функция OnClose будет возвращена перед самым закрытием Рабочего места, но уже после того как закрыты все таблицы и окна. Таков дизайн этой функции.
Понять закрыто ли конкретное окно можно с помощью функции IsWindowClosed, что вам удалось продемонстрировать в изначальном сообщении.
Т.о. колбек OnClose приходит лишь при полном закрытии приложения терминала.
 
Цитата
Oleg Kuzembaev написал:
Добрый день.

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

В итоге понять, что терминал закрывается, и необходимо изменить алгоритм обработки окон, таблиц, графиков из main - нельзя. Поэтому и требуется флаг, сигнализирующий о начале процесса закрытия терминала.
 
Цитата
Oleg Kuzembaev написал:
Добрый день.

Функция OnClose будет возвращена перед самым закрытием Рабочего места, но уже после того как закрыты все таблицы и окна. Таков дизайн этой функции.
Понять закрыто ли конкретное окно можно с помощью функции IsWindowClosed, что вам удалось продемонстрировать в изначальном сообщении.
Т.о. колбек OnClose приходит лишь при полном закрытии приложения терминала.
Сообщение об аварийной ситуации на борту приходит к пассажирам самолета перед самым закрытием Рабочего места за секунду до встречи с землёй


у скриптов уже украли окна. Судя по всему, уже не приходят колбеки. Что еще недоступно в краткий миг последнего метра над уровнем земли?
Страницы: 1
Читают тему
Наверх