DestroyTable (и Clear) закрывает скрипт вместо таблицы, Тема описана в Названии и в Тексте сообщения
Пользователь
Сообщений: Регистрация: 31.01.2015
01.10.2025 22:28:58
Версия Quik 12.5.0.20. Код скрипта
Код
function OnStop (signal)
StopFlag = true
return 1000 -- Тайм-аут 1 сек вместо стандартных 5
end
function Create (caption, rowNum, cols)
local t_id = AllocTable()
for i = 1, #cols do -- name * type width
assert (1==AddColumn (t_id,i,cols[i][1],true,cols[i][2],cols[i][3])
,string.format ("%2d %s %s %s", i, tostring(cols[i][1])
,tostring (cols[i][2]), tostring (cols[i][3])))
end -- * false - all cells invisible
assert (1 == CreateWindow (t_id))
assert (SetWindowCaption (t_id, caption))
local top, left, bottom, right = GetWindowRect (t_id)
local totalWidth = right - left + 10 -- Эмпирика |
local frameHeight = 60 --"- |
local rowHeight = 20 --"- |
for i = 1, rowNum do
local row = InsertRow (t_id, -1)
assert (row == i)
assert (SetCell (t_id, row, 1, "row".. i))
for j = 2, #cols do
local val = i * 10 + j
assert (SetCell (t_id, row, j, tostring(val), val))
end
end
assert (SetWindowPos (t_id, left, top
,totalWidth, frameHeight + rowHeight * rowNum))
return t_id
end -- Cre ate ()
function main()
local rowNum = 2
local cols = {
{"Column1", QTABLE_STRING_TYPE, 10,}
,{"Column2", QTABLE_INT_TYPE, 10,}
,{"Column3", QTABLE_DOUBLE_TYPE, 10,}
}
local t_id = Create ("Caption", rowNum, cols)
while not IsWindowClosed (t_id) do
if StopFlag then
message ("Destroying ".. t_id)
if DestroyTable (t_id) then -- Завершение!
message ("Destroying success ".. t_id)
else
message ("Destroying failed ".. t_id)
end
break
end
sleep (10)
end -- while
end -- main()
Будет выход из цикла и функции main при закрытии таблицы и это правильно. В данном случае ошибки в Qlua нет.
Пользователь
Сообщений: Регистрация: 31.01.2015
11.10.2025 12:36:10
В моём скрипте закодировано его закрытие не сразу после закрытия таблицы DestroyTable, а после вывода сообщения о закрытии таблицы. Так что неправда ваша, что закрытие реализовано в моём скрипте. Это закрытие реально - в операторе DestroyTable> который должен возвоащать логическое значение, но вопреки документации - не возвращает ничего. Вчитайтесь пожалуйста в код цикла while not IsWindowClosed (t_id) do...
Пользователь
Сообщений: Регистрация: 31.01.2015
11.10.2025 15:29:22
В каком потоке управления выполняется вызов функции DestroyTable() в цикле while not IsWindowClosed (t_id) do... ? Если в том же, что и заголовок цикла, то проверка IsWindowClosed() никак не может сработать раньше возврата значения из DestroyTable() и обработки этого значения в операторе if DestroyTable(t_id) then... Обработка логического значения из DestroyTable() завершается выводом message и оператором break, что исключает срабатывание IsWindowClosed (t_id) в заголовке цикла while. Но печатается только перед функцией DestroyTable(), а сразу после неё - скрипт уже завершён.
Пользователь
Сообщений: Регистрация: 12.05.2020
11.10.2025 19:01:44
Цитата
Ростислав Дм. Кудряшов написал: В каком потоке управления выполняется вызов функции DestroyTable()
Работа с таблицами QUIK выполняется в служебном потоке, отличном от main. В том же, в котором выполняется OnStop. И пока выполняется OnStop никакие операции с таблицами QUIK не возможны (поток работы с таблицами занят OnStop ). OnStop в любом случае завершает скрипт, поэтому DestroyTable не выполнена и созданная в скрипте таблица существует после завершения скрипта. Если что то надо делать с таблицами по кнопке завершить, то это надо делать в функции OnStop.
написал: В каком потоке управления выполняется вызов функции DestroyTable()
Работа с таблицами QUIK выполняется в служебном потоке, отличном от main. В том же, в котором выполняется OnStop. И пока выполняется OnStop никакие операции с таблицами QUIK не возможны (поток работы с таблицами занят OnStop ). OnStop в любом случае завершает скрипт, поэтому DestroyTable не выполнена и созданная в скрипте таблица существует после завершения скрипта. Если что то надо делать с таблицами по кнопке завершить, то это надо делать в функции OnStop.
Полагаю, что не так. -------------------- Поток, если не создается специально для функции, определяется местом вызова. ---------------------- Все колбеки ( в том числе ОnStop ) вызываются в основном потоке VMLua (т е в потоке терминала). --------------------------- Функция DestroyTable в данном примере вызывается в потоке Main.
Зачем полагать, когда можно проверить. Переставьте DestroyTable в OnStop.
2.
Цитата
nikolz написал: Функция DestroyTable в данном примере вызывается в потоке Main.
Вы точно знаете как устроена DestroyTable? Не точно, но скорее всего, это реализовано следующим образом. При том, что DestroyTable вызывается в main, она не лезет в таблицы QUIK, а создает коллбек закрытия таблицы, который обрабатывается в потоке терминала, но он занят более интересным делом : остановкой скрипта (удаляет поток main и перестает обрабатывать коллбеки, созданные в нем, так как исчезнет контекст их выполнения).
Зачем полагать, когда можно проверить. Переставьте DestroyTable в OnStop.
2.
Цитата
написал: Функция DestroyTable в данном примере вызывается в потоке Main.
Вы точно знаете как устроена DestroyTable? Не точно, но скорее всего, это реализовано следующим образом. При том, что DestroyTable вызывается в main, она не лезет в таблицы QUIK, а создает коллбек закрытия таблицы, который обрабатывается в потоке терминала, но он занят более интересным делом :: : остановкой скрипта (удаляет поток main и перестает обрабатывать коллбеки, созданные в нем, так как исчезнет контекст их выполнения).
Что-то у Вас не то. Колбек не создается в процессе исполнения. Колбек - это код функции , он создан при загрузке программы. Если он вызывается в main то вызов это и есть исполнение.
Пользователь
Сообщений: Регистрация: 12.05.2020
13.10.2025 16:14:37
Цитата
nikolz написал: Если он вызывается в main то вызов это и есть исполнение.
nikolz писатель ? Читайте:
Цитата
TGB написал: она не лезет в таблицы QUIK, а создает коллбек закрытия таблицы, который обрабатывается в потоке терминала,
Пользователь
Сообщений: Регистрация: 20.03.2023
14.10.2025 07:54:48
Скорее не коллбек, а какой-то семафор, нужный для операций с окнами, заблокирован от момента нажатия на кнопку "Остановить" до завершения. Не только DestroyTable(), любые операции с таблицей не выполняются. Если к примеру вызвать SetWindowCaption(), возврата из нее не будет, но после таймаута остановки заголовок окна таки изменится.
Пользователь
Сообщений: Регистрация: 12.05.2020
14.10.2025 08:08:47
Цитата
paluke написал: Не только DestroyTable(), любые операции с таблицей не выполняются.
Цитата
TGB написал: Работа с таблицами QUIK выполняется в служебном потоке, отличном от main. В том же, в котором выполняется OnStop. И пока выполняется OnStop никакие операции с таблицами QUIK не возможны (поток работы с таблицами занят OnStop ).
Пользователь
Сообщений: Регистрация: 31.01.2015
15.10.2025 14:07:48
Оказывается, после захода управления в OnStop для кода main() функция DestroyTable() не может выполняться штатным образом. Если нужно отреагировать на OnStop, надо туда же поместить и вызовы DestroyTable(). После захода в OnStop() функция main() может делать ещё кое-что, но хотелось бы знать полный список ограничений на этот случай. То ли я плохо прочитал документацию по Quik Lua, то ли документация не полная.
Действительно, в настоящий момент остановка работы скрипта блокирует возможность работы его основного потока с таблицами в РМ QUIK. Если после остановки скрипт перед завершением работы попытается удалить какую-либо таблицу или взаимодействовать с ней иным образом, то скрипт может зависнуть и будет принудительно остановлен. Данная проблема будет исправлена в очередных версиях терминала Quik.
В качестве временного решения рекомендуем пока вынести удаление таблиц в функцию OnStop() и не строить логику завершения работы скрипта вокруг состояния окон.
function OnStop (signal)
StopFlag = true
return 1000 -- Тайм-аут 1 сек вместо стандартных 5
end
function Create (caption, rowNum, cols)
local t_id = AllocTable ()
for i = 1 , # cols do -- name * type width
assert ( 1 = = AddColumn (t_id,i,cols[i][ 1 ], true ,cols[i][ 2 ],cols[i][ 3 ])
,string.format ( "%2d %s %s %s" , i, tostring(cols[i][ 1 ])
,tostring (cols[i][ 2 ]), tostring (cols[i][ 3 ])))
end -- * false - all cells invisible
assert ( 1 = = CreateWindow (t_id))
assert ( SetWindowCaption (t_id, caption))
local top, left, bottom, right = GetWindowRect (t_id)
local totalWidth = right - left + 10 -- Эмпирика |
local frameHeight = 60 --"- |
local rowHeight = 20 --"- |
for i = 1 , rowNum do
local row = InsertRow (t_id, - 1 )
assert (row = = i)
assert ( SetCell (t_id, row, 1 , "row" .. i))
for j = 2 , # cols do
local val = i * 10 + j
assert ( SetCell (t_id, row, j, tostring(val), val))
end
end
assert ( SetWindowPos (t_id, left, top
,totalWidth, frameHeight + rowHeight * rowNum))
return t_id
end -- Cre ate ()
function main ()
local rowNum = 2
local cols = {
{"Column1", QTABLE_STRING_TYPE, 10 ,}
,{"Column2", QTABLE_INT_TYPE, 10 ,}
,{"Column3", QTABLE_DOUBLE_TYPE, 10 ,}
}
local t_id = Create ( "Caption" , rowNum, cols)
while not IsWindowClosed (t_id) do
if StopFlag then
message ( "Destroying " .. t_id)
if DestroyTable (t_id) then -- Завершение!
message ( "Destroying success " .. t_id)
else
message ( "Destroying failed " .. t_id)
end
break
end
sleep ( 10 )
end -- while
end -- main()
---
не удалось повторить , скрипт закрывает окно. что не так?
Пользователь
Сообщений: Регистрация: 30.01.2015
16.10.2025 11:06:58
Разобрался Исправил скрипт так:
Код
function OnStop (signal)
message ("Destroying ".. t_id)
if DestroyTable (t_id) then -- Завершение!
message ("Destroying success ".. t_id)
else
message ("Destroying failed ".. t_id)
end
StopFlag = true
return 1000 -- Тайм-аут 1 сек вместо стандартных 5
end
function Create (caption, rowNum, cols)
local t_id = AllocTable()
for i = 1, #cols do -- name * type width
assert (1==AddColumn (t_id,i,cols[i][1],true,cols[i][2],cols[i][3])
,string.format ("%2d %s %s %s", i, tostring(cols[i][1])
,tostring (cols[i][2]), tostring (cols[i][3])))
end -- * false - all cells invisible
assert (1 == CreateWindow (t_id))
assert (SetWindowCaption (t_id, caption))
local top, left, bottom, right = GetWindowRect (t_id)
local totalWidth = right - left + 10 -- Эмпирика |
local frameHeight = 60 --"- |
local rowHeight = 20 --"- |
for i = 1, rowNum do
local row = InsertRow (t_id, -1)
assert (row == i)
assert (SetCell (t_id, row, 1, "row".. i))
for j = 2, #cols do
local val = i * 10 + j
assert (SetCell (t_id, row, j, tostring(val), val))
end
end
assert (SetWindowPos (t_id, left, top
,totalWidth, frameHeight + rowHeight * rowNum))
return t_id
end -- Cre ate ()
function main()
local rowNum = 2
local cols = {
{"Column1", QTABLE_STRING_TYPE, 10,}
,{"Column2", QTABLE_INT_TYPE, 10,}
,{"Column3", QTABLE_DOUBLE_TYPE, 10,}
}
t_id = Create ("Caption", rowNum, cols)
while not IsWindowClosed (t_id) do
sleep (10)
end -- while
end -- main()
Все работает нормально.
Пользователь
Сообщений: Регистрация: 30.01.2015
16.10.2025 11:09:01
пардон, еще исправление:
Код
function OnStop (signal)
message ("Destroying ".. t_id)
if DestroyTable (t_id) then -- Завершение!
message ("Destroying success ".. t_id)
else
message ("Destroying failed ".. t_id)
end
StopFlag = true
return 1000 -- Тайм-аут 1 сек вместо стандартных 5
end
function Create (caption, rowNum, cols)
t_id = AllocTable()
for i = 1, #cols do -- name * type width
assert (1==AddColumn (t_id,i,cols[i][1],true,cols[i][2],cols[i][3])
,string.format ("%2d %s %s %s", i, tostring(cols[i][1])
,tostring (cols[i][2]), tostring (cols[i][3])))
end -- * false - all cells invisible
assert (1 == CreateWindow (t_id))
assert (SetWindowCaption (t_id, caption))
local top, left, bottom, right = GetWindowRect (t_id)
local totalWidth = right - left + 10 -- Эмпирика |
local frameHeight = 60 --"- |
local rowHeight = 20 --"- |
for i = 1, rowNum do
local row = InsertRow (t_id, -1)
assert (row == i)
assert (SetCell (t_id, row, 1, "row".. i))
for j = 2, #cols do
local val = i * 10 + j
assert (SetCell (t_id, row, j, tostring(val), val))
end
end
assert (SetWindowPos (t_id, left, top
,totalWidth, frameHeight + rowHeight * rowNum))
return t_id
end -- Cre ate ()
function main()
local rowNum = 2
local cols = {
{"Column1", QTABLE_STRING_TYPE, 10,}
,{"Column2", QTABLE_INT_TYPE, 10,}
,{"Column3", QTABLE_DOUBLE_TYPE, 10,}
}
t_id = Create ("Caption", rowNum, cols)
while not IsWindowClosed (t_id) do
sleep (10)
end -- while
end -- main()
Пользователь
Сообщений: Регистрация: 30.01.2015
16.10.2025 11:40:15
Рекомендую сделать так:
Код
function OnStop (signal)
if t_id then DestroyTable (t_id) end -- Завершение!
StopFlag = true
return 1000 -- Тайм-аут 1 сек вместо стандартных 5
end
function Create (caption, rowNum, cols)
local rowNum = 2
local cols = {
{"Column1", QTABLE_STRING_TYPE, 10,}
,{"Column2", QTABLE_INT_TYPE, 10,}
,{"Column3", QTABLE_DOUBLE_TYPE, 10,}
}
t_id = AllocTable()
for i = 1, #cols do -- name * type width
assert (1==AddColumn (t_id,i,cols[i][1],true,cols[i][2],cols[i][3])
,string.format ("%2d %s %s %s", i, tostring(cols[i][1])
,tostring (cols[i][2]), tostring (cols[i][3])))
end -- * false - all cells invisible
assert (1 == CreateWindow (t_id))
assert (SetWindowCaption (t_id, caption))
local top, left, bottom, right = GetWindowRect (t_id)
local totalWidth = right - left + 10 -- Эмпирика |
local frameHeight = 60 --"- |
local rowHeight = 20 --"- |
for i = 1, rowNum do
local row = InsertRow (t_id, -1)
assert (row == i)
assert (SetCell (t_id, row, 1, "row".. i))
for j = 2, #cols do
local val = i * 10 + j
assert (SetCell (t_id, row, j, tostring(val), val))
end
end
assert (SetWindowPos (t_id, left, top
,totalWidth, frameHeight + rowHeight * rowNum))
end -- Cre ate ()
function main()
if t_id==nil then Create ("Caption", rowNum, cols) end
while StopFlag==nil do sleep (10) end
end -- main()
Пользователь
Сообщений: Регистрация: 30.01.2015
16.10.2025 11:44:03
Код
function OnStop (signal)
if t_id then DestroyTable (t_id) end -- Завершение!
StopFlag = true
return 1000 -- Тайм-аут 1 сек вместо стандартных 5
end
function Create (caption, rowNum, cols)
t_id = AllocTable()
for i = 1, #cols do -- name * type width
assert (1==AddColumn (t_id,i,cols[i][1],true,cols[i][2],cols[i][3])
,string.format ("%2d %s %s %s", i, tostring(cols[i][1])
,tostring (cols[i][2]), tostring (cols[i][3])))
end -- * false - all cells invisible
assert (1 == CreateWindow (t_id))
assert (SetWindowCaption (t_id, caption))
local top, left, bottom, right = GetWindowRect (t_id)
local totalWidth = right - left + 10 -- Эмпирика |
local frameHeight = 60 --"- |
local rowHeight = 20 --"- |
for i = 1, rowNum do
local row = InsertRow (t_id, -1)
assert (row == i)
assert (SetCell (t_id, row, 1, "row".. i))
for j = 2, #cols do
local val = i * 10 + j
assert (SetCell (t_id, row, j, tostring(val), val))
end
end
assert (SetWindowPos (t_id, left, top
,totalWidth, frameHeight + rowHeight * rowNum))
end -- Cre ate ()
function main()
local rowNum = 2
local cols = {
{"Column1", QTABLE_STRING_TYPE, 10,}
,{"Column2", QTABLE_INT_TYPE, 10,}
,{"Column3", QTABLE_DOUBLE_TYPE, 10,}
}
while StopFlag==nil do
if t_id==nil then Create ("Caption", rowNum, cols) end
sleep (10)
end
end -- main()