Расширить список функций обратного вызова

Страницы: 1
RSS
Расширить список функций обратного вызова
 
Не помню, предлагали уже такие пожелания или нет.

1) Добавить функцию обратного вызова OnTimer(), которая будет вызываться терминалом с некоторой периодичностью. Надо понять, как указывать период срабатывания. Конкретно для моих задач хватит срабатывания раз в секунду, но мало ли кому чаще надо. Предлагаю обсудить, кому интересно.

Пускай первый раз функция OnTimer() запускается сразу после OnInit() и возвращает число число миллисекунд, через которое будет сделан следующий вызов функции OnTimer(). Если возвращается не число, то пусть следующий вызов будет через 1 секунду.

Реализация на стороне терминала кажется несложной.

2) Дать пользователю возможность из main-потока подать команду на запуск своей функции в потоке коллбэков. Нормальное название не придумал, но надо что-то типа
Код
 executeAsCallback(function() ... end)

В принципе, имея п.2, пользователь сможет самостоятельно реализовать п.2, если только в main-потоке не выполняются тяжёлые вычислительные задачи.

Надо всё это для того, чтобы можно было выполнять в потоке коллбэков регулярные задачи, которые удобнее и архитектурно правильнее делать там, а не в main.
 
1) Вам main() зачем дадена?
Код
main()
   while run do
      sleep(1000)
      DoMyFunc()   -- вот и "таймер" раз в секунду
   end
end


2) А зачем? что плохого в выполнении в нужного кода опять же в main() ?
 
1) OnTimer прекрасно эмулируется в цикле со sleep, там же указывается период срабатывания (у меня их даже два: раз в полторы секунды и раз в 15 секунд). А никакого OnInit вообще нет.

2) С потоками разработчики вообще перемудрили - нельзя туда пускать юзера вообще, не его это свинячье дело, в каком потоке что выполнять. И так уже управление теряется между потоками, а коллбеки способны подвесить Квик!
 
Пункт 2 я предлагал в несколько другой редакции, сейчас передумал. Причина: единственное ожидаемое применение - обойти зависание при работе с таблицами, пока квик ждет завершения мейна. Но сам заказ колбека придется посылать той же SendMessage (а как иначе), в результате вместо зависания на таблице зависнем на отправке колбека.

Пункт 1 по-моему так должен формулироваться
Код
BOOLEAN setTimer(INTEGER timeout_ms, FUNCTION callback)
и прототип колбека
Код
INTEGER CALLBACK timerCallback(VOID)
Если колбек возвращает отрицательное число, данный таймер прибивается. Если ноль или больше - меняется период таймера на возвращенное значение. Интересный крайний случай при периоде 0 - это тот же немедленный вызов колбека в потоке квика.
 
Антон, спасибо за предложенные варианты по п.1. Опасения по поводу п.2 понял. Получается, что лучше просить разработчиков реализовать п.1.

swerg, я же не просто так написал, что
Цитата
Надо всё это для того, чтобы можно было выполнять в потоке коллбэков  регулярные задачи, которые удобнее и архитектурно правильнее делать там,  а не в main.
 
Цитата
Anton написал:
SendMessage (а как иначе)

Через PostMessage, конечно
Кстати, 1) есть у меня (ну почти, сделал, не подумал зачем это может понадобится, выкинул, но восстановить не сложно)
 
Цитата
_sk_ написал:
Надо всё это для того, чтобы можно было выполнять в потоке коллбэков  регулярные задачи, которые удобнее и архитектурно правильнее делать там,  а не в main.

Архитектурно правильно (в тех рамках, что мы имеем) как можно меньше нагружать колбеки основного потока, вынося всё что возможно в main(). Некоторые еще и несколько потоков делают, этакие множественные main(). Или даже в отдельный процесс.
А потому всё же хотелось бы услышать что это за такие "архитектурно правильные задачи", которые нельзя вынести в main().
 
Цитата
swerg написал:
Кстати, 1) есть у меня

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

Если пробрасывать события из потока коллбэков в поток main(), то будут возникать задержки, чего не стоит допускать.

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

Выходит, что удобно иметь возможность инициировать какой-то коллбэк из потока main, не надо думать про синхронизацию. Пункты 1 и 2 были обсуждением таких возможностей.
 
Костыли типа отправки какой-нибудь транзакции на сервер, чтобы OnTransReply сработал, не предлагать.
 
Цитата
_sk_ написал:
Есть потребность в отключении слушателей по таймауту (а не когда придёт очередной коллбэк)

"Отключить слушателей по таймауту (а не когда придёт очередной коллбэк)" абсолютно эквивалентно "в начале колбека проверить надо ли уведомлять этого конкретного слушателя или таймаут его уведомлений истёк".      В целом вся эта машинерия выглядит через чур запутанной, потом же сами концов в ней не найдёте... "Почему этот слушатель не сработал? то ли по тайм-ауту отключили, то ли колбека не было, то ли просто что-то пошло не так." "Архитектурно-правильно".... но это так, мысли вслух
 
Цитата
_sk_ написал:
Костыли типа отправки какой-нибудь транзакции на сервер, чтобы OnTransReply сработал, не предлагать.
А если без сетевого обмена костылик? Поглядите
Код
local run = true
local tid = nil

function main()
   tid = AllocTable()
   AddColumn(tid, 1, '1', true, QTABLE_INT_TYPE, 1)
   CreateWindow(tid)
   InsertRow(tid, -1)
   InsertRow(tid, -1)
   SetWindowPos(tid, 0, 0, -1000, -1000)
   SetSelectedRow(tid, 1)
   SetTableNotificationCallback(tid, function(t, m, w, l)
      if QTABLE_SELCHANGED == m then
         if 2 == w then
            SetSelectedRow(t, 1)
            message('!')
         end
      end
   end)
   while run do
      sleep(1000)
      SetSelectedRow(tid, 2)
   end
   OnStop()
end

function OnStop()
   local t = tid
   tid = nil
   if t then
      DestroyTable(t)
   end
   run = false
end
Создаем окошко с двумя строчками, выделяем первую, ставим колбек на изменение выделения, в колбеке возвращаем выделение в первую строку. Когда надо колбек выполнить в квиковском потоке, меняем выделение на вторую строку и вуаля, тут же отрабатывает колбек, чего мы и хотели. Вместо message(), естественно, вызываем что-то свое полезное.
 
Идея прикольная :) Осталось окно скрипта куда-нибудь спрятать и будет "зачётный костыль".

Терминал является уже достаточно сложной системой, чтобы в нём были такого рода "дыры", которыми можно пользоваться в благих целях.

Ладно, а разработчики могут нам что-то человеческое предоставить?

P.S. Вот было бы здорово создать реестр подобного рода маленьких хитростей. А то я, кажется, только
Код
table.ssort({ 0, 1 }, function(a, b)
Ваш код здесь
return true
end)

для синхронизации знаю.
 
Цитата
_sk_ написал:
Осталось окно скрипта куда-нибудь спрятать
Если полосы прокрутки выключены, можно спрятать в позицию (-1000, -1000), со включенными не придумал куда. С помощью длл можно скрыть, но тогда можно и совсем без окна обойтись.
 
Цитата
Владимир написал:
1) OnTimer прекрасно эмулируется в цикле со sleep, там же указывается период срабатывания (у меня их даже два: раз в полторы секунды и раз в 15 секунд). А никакого OnInit вообще нет.
Подскажите, а как вам удается два цикла со sleep сделать? Вы внутри main их делаете? или внутри какого-то колбека?

Я тоже использую sleep в main, но насколько я исследовал этот вопрос, когда идет функция sleep он полностью прекращает свою работу и просто ждет это время
 
Sergey Denegin, Элементарно, Господи! И не нужно никаких "два цикла со sleep". Вот кусок main:
Код
while f do -- бесконечный цикл до остановки скрипта
 if fm>3 then DestroyTable(t);fm=0;end;
 if fm==3 then DestroyTable(t);fm=1;end;
 if fm==1 then u();fm=2;end;   -- рисуем или убираем всплывающее меню
 r();-- раз в 1.5 секунды запускаем утилиту опроса
sleep(1500);   -- текущих данных и принятия решений по ним
end;   -- конец бесконечного цикла
end;   -- конец функции main()

А вот эмулятор обработчика:
Код
function r()   -- мелкий обработчик прерывания по таймеру
 c=c+1;      -- счётчик прерываний
 if c==10 then c=0; R();end;   -- прошло 15 секунд, включаем анализ
...
КТО ИМЕННО "полностью прекращает свою работу и просто ждет это время"? Скрипт? Так это просто интерпретируемый текст - он вообще никогда не работает.  :smile:  
Страницы: 1
Читают тему (гостей: 1)
Наверх