Проблема с выводом в пользовательскую таблицу

Страницы: 1
RSS
Проблема с выводом в пользовательскую таблицу
 
Есть вот такой простенький код:
Код
IsRun = true


function TableCreate()

  g_tid = AllocTable()

  if (g_tid ~= nil) then

    SetTableNotificationCallback(g_tid, OnTableEvent)

    AddColumn(g_tid, 1, "Сообщение", true, QTABLE_STRING_TYPE, 100)

    if (CreateWindow(g_tid)) then

      SetWindowCaption(g_tid, "Таблица")

      SetWindowPos(g_tid, 0, 0, 800, 200)

    else

      DestroyTable(g_tid)

      g_tid = nil

    end

  end

end


function OnTableEvent(tid, msg, par1, par2)

  PrintDbgStr("OnLogTableEvent enter")

  PrintDbgStr("OnLogTableEvent leave")

end


function OnInit(script)

  PrintDbgStr("OnInit enter")

  TableCreate()

  local row = InsertRow(g_tid, -1)
  SetCell(g_tid, row, 1, "OnInit: Скрипт запущен.")

  PrintDbgStr("OnInit leave")

end


function OnStop(signal)

  PrintDbgStr("OnStop enter")

  IsRun = false

  local row = InsertRow(g_tid, -1)
  SetCell(g_tid, row, 1, "OnStop: Скрипт остановлен.")

  PrintDbgStr("OnStop leave")

end


function main()

  PrintDbgStr("main enter")

  local row = InsertRow(g_tid, -1)
  SetCell(g_tid, row, 1, "main: Скрипт запущен.")

  while (IsRun) do

    sleep(500)

  end

  local row = InsertRow(g_tid, -1)
  SetCell(g_tid, row, 1, "main: Скрипт остановлен.")

  PrintDbgStr("main leave")

end

При его запуске в отладочную консоль выводятся строки:

Код
OnInit enter
OnInit leave
main enter

Появляется окно с таблицей и в неё выводятся строки:

Код
OnInit: Скрипт запущен.
main: Скрипт запущен.

До этого момента всё работает как надо. Если же далее остановить скрипт из диалога управления, то в консоль выводятся строки:

Код
OnStop enter
OnStop leave

Далее окно диалога управления подвисает на 5 секунд. Откуда это время понятно, ожидание завершения потока функции main по умолчанию.

И только сейчас, по истечении этого времени в окне с таблицей появляется строка:

Код
OnStop: Скрипт остановлен.

хотя колл-бэк функция OnStop уже давно отработала, судя по выводу в консоли.

Строка "main: Скрипт остановлен." в окне с таблицей не появляется совсем, т.к. и скорее всего поток main уже принудительно завершен. Соответственно и сообщение "main leave" в консоли тоже не появляется.
Почему виснет очередь сообщений к окну таблицы при остановке скрипта? Как обработать такую ситуацию, если нужен вывод в пользовательскую таблицу по завершении потока main?
 
Цитата
e2e4 написал:
Почему виснет очередь сообщений к окну таблицы при остановке скрипта?
1. Вы жмете кнопку остановить.
2. Основной поток квика вызывает OnStop.
3. OnStop добавляет свою строку в таблицу (таки да, добавляет).
4. OnStop завершается.
5. Основной поток ждет завершения потока мейна пять секунд.
6. В это время мейн пытается добавить свою строку в таблицу, посылая под ковром сообщение основному потоку.
7. Но так как см. п.5, основной поток сообщений не обрабатывает. Мейн виснет навсегда.
8. По истечении таймаута основной поток прибивает поток мейна и продолжает обработку сообщений.
9. Выбрав все ценные, он ловит наконец низкоприоритетное WM_PAINT и перерисовывает таблицу (вот тут появилась строка от OnStop).
10. Хэппиенд.

Цитата
e2e4 написал:
Как обработать такую ситуацию, если нужен вывод в пользовательскую таблицу по завершении потока main?
Не знаю.
 
Цитата
e2e4 написал:
Далее окно диалога управления подвисает на 5 секунд. Откуда это время понятно, ожидание завершения потока функции main по умолчанию.
А мне не понятно откуда в этом коде возникает этот timeout
Вроде всё должно завершиться сразу и корректно, т.к. в OnStop есть IsRun = false
Чисто для прикола отлогируйте значение IsRun из main() и других мест, ну мало-ли какая мистика.

Пока похоже на косяки обработки обращения к пользовательским таблицам из main(), вроде про это были жалобы на форуме.
 
Цитата
swerg написал:
А мне не понятно откуда в этом коде возникает этот timeout
На InsertRow после цикла встает. Если закомментировать эти две строки, не будет вставать.
 
Цитата
Anton написал:
спасибо за ответ, всё так просто и логично оказалось, теперь стало понятнее, сам бы наверное не допёр, особенно про перерисовку по WM_PAINT.
сделал проверку, что если скрипт останавливается вручную, то вывода из main в таблицу не будет, а будет из OnStop и наоборот.
 
Цитата
e2e4 написал:
и наоборот.
Когда наоборот, все проще, мейн закончился и колбеки больше не дергаются.

Если находитесь в длл, придумал костылек (адоватенький), некий псевдо-луа-си
Код
function OnStop()
  InsertRow
  SetCell
  isRun = false
  for(; !isRun; )
  {
    for(MSG msg; PeekMessage(&msg, ...); )
    {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }
  }
end

function main()
   ...
   isRun = true
end
Проверять не проверял. Там еще где-то надо воткнуть WaitMessage, если isRun все еще не установлен и сообщений нет, но как-то так, чтобы не повиснуть на ней навечно.
 
Цитата
Anton написал:
вставлять свой цикл обработки сообщений - это сложновато ещё для меня :smile:  
длл для вызова winapi из lua не использую, только свой длл-код по необходимости
мне не ясна была логика работы, на чем ожидает/подвисает, а Вы мне объяснили, спс
внес поправки, теперь как-бы всё устраивает
 
Тов. из QUIK software testing обещал разобраться с этим. И пропал. Видимо, разбирается.
Цитата
e2e4 написал:
сделал проверку, что если скрипт останавливается вручную, то вывода из main в таблицу не будет, а будет из OnStop и наоборот
Но, если есть обращения к таблице в main внутри цикла while isRun do, тут уже сложнее.
Чтобы QUIK не подвисал при остановке, и скрипт корректно завершался, первым делом в OnStop удаляю идентификатор таблицы.
Надо делать так, как надо. А как не надо - делать не надо.
 
Цитата
Старатель написал:
так точно, спасибо,  пока и сам остановился на данном способе, я про обнуление идентификатора таблицы в OnStop
так даже проще, ничего проверять не нужно
Страницы: 1
Читают тему
Наверх