Russian Qt Forum

Qt => Многопоточное программирование, процессы => Тема начата: Vamireh от Август 22, 2013, 16:19



Название: Таймеры и потоки
Отправлено: Vamireh от Август 22, 2013, 16:19
Нужно прочитать из файла список команд и выполнить их. Упрощенно имеются классы:
  • Window - главное окно
  • ScriptWorker:QObject - выполняет скрипт
  • Device:QObject - для работы с неким устройством

В Window по нажатию кнопки "выполнить скрипт":
Код:
QThread *thread = new QThread;
Worker* worker = new Worker;
worker->moveToThread(thread)
connect (thread->started, worker->execScript);
thread->start;

В Worker в методе execScript:
Код:
Device device = new Device;
foreach(commands)
    do current command;

Все работает, кроме чтения из COM портов. Класс Device читает данные из устройства по таймеру, который не работает, т.к. нужно где-то запустить QThread::exec();
Вопрос где его запускать в этой схеме работы или посоветуйте другую схему.


Название: Re: Таймеры и потоки
Отправлено: mutineer от Август 22, 2013, 16:24
QThread::exec() запускается внутри дефолтной реализации QThread::run()


Название: Re: Таймеры и потоки
Отправлено: Vamireh от Август 22, 2013, 16:26
QThread::exec() запускается внутри дефолтной реализации QThread::run()

Да, но тем не менее timerEvent() в классе Device не срабатывают


Название: Re: Таймеры и потоки
Отправлено: mutineer от Август 22, 2013, 16:31
А когда он должен сработать?
Девайс создается в функции execScript и как долго живет?


Название: Re: Таймеры и потоки
Отправлено: Vamireh от Август 22, 2013, 16:48
Да, девайс создается в execScript и живет все время выполнения этой функции. В execScript циклом проходится по всем командам и их выполняет, например:
- задать напряжение источника тока
- включить изделие
- минуту подождать
- выключить изделие
- сохранить снятые данные

в девайсе в конструкторе запускается таймер, по событию которого считываются данные и вносятся в массив. Так вот, изделие включается, ждется минута, изделие выключается, сохраняется пустой файл. При этом событие таймера ни разу на срабатывает.


Название: Re: Таймеры и потоки
Отправлено: mutineer от Август 22, 2013, 16:50
А ожидание как реализовано?
Если всю эту минуту поток стоит внутри этой функции, то таймер не сможет вызвать timerEvent (поток за минуту ни разу не вернется в EventLoop)


Название: Re: Таймеры и потоки
Отправлено: Vamireh от Август 22, 2013, 16:58
Ожидание - Sleep из WinAPI, или nanosleep под Linux. Да и дело не в задержки, мне кажется. Я так же ни одного ответа от устройств не получаю, если просто слать подготовительные операции без задержек. Если Device создать прямо в Window и управлять им вручную кнопками, то все работает, если что.


Название: Re: Таймеры и потоки
Отправлено: mutineer от Август 22, 2013, 17:00
В слипе проблема. Чтобы отработал таймер потоку надо вернуться в EventLoop и оттуда вызвать обработчик события таймера. А поток спит внутри execScript и в EventLoop не возвращается


Название: Re: Таймеры и потоки
Отправлено: Vamireh от Август 22, 2013, 17:08
В свое время для другого места программы создал функцию sleep, которая делит время сна на маленькие куски, между которыми выполняется QApplication::processEvents() чтобы не было заморозки интерфейса. Здесь это поможет? Проверить только завтра смогу


Название: Re: Таймеры и потоки
Отправлено: mutineer от Август 22, 2013, 17:09
В принципе поможет, но возможно лучше будет запустить локальный EventLoop и запилить таймер, по которому он завершится


Название: Re: Таймеры и потоки
Отправлено: Vamireh от Август 22, 2013, 18:02
ок, завтра проверю


Название: Re: Таймеры и потоки
Отправлено: Vamireh от Август 23, 2013, 16:42
да, все работает спасибо. правда с парой нюансов, например, между командами нужно задержку сделать в 1000мс, с 500мс задержкой все равно не работает.


Название: Re: Таймеры и потоки
Отправлено: gil9red от Август 23, 2013, 16:45
Ожидание - Sleep из WinAPI, или nanosleep под Linux. Да и дело не в задержки, мне кажется. Я так же ни одного ответа от устройств не получаю, если просто слать подготовительные операции без задержек. Если Device создать прямо в Window и управлять им вручную кнопками, то все работает, если что.
насчет задержки в потоках, юзайте соответствующие sleep'ы у вашего наследника QThread (msleep, usleep) - они будут кросплатформенными :)


Название: Re: Таймеры и потоки
Отправлено: mutineer от Август 23, 2013, 16:46
что именно не работает и что за задержка между командами?


Название: Re: Таймеры и потоки
Отправлено: Vamireh от Август 23, 2013, 20:01
если между командами этого скрипта запускать QEventLoop на секунду, то все работает. если этого не делать или даже на полсекунды запустить, то... ну в общем PortMon чтение из портов фиксирует, но не сразу, а через несколько записей в порты, например, отправил команду, полсекунды евентлупа, отправил вторую команду, полсекунды евентлупа, отправил третью команду, получил ответ на первую команду.


Название: Re: Таймеры и потоки
Отправлено: mutineer от Август 25, 2013, 13:39
Команды в порт сразу уходят или копятся в буфере каком-то?


Название: Re: Таймеры и потоки
Отправлено: kuzulis от Август 25, 2013, 14:34
Если речь идет о последовательных портах, то никакие слипы, потоки и пр. не нужно, если использовать QtSerialPort (http://qt-project.org/wiki/QtSerialPort). Если же используется свое решение - то это для тех, кто хочет помудохаться потерять время.  :)