Название: Непонятная проблема с передачей QString из потока Отправлено: Гурман от Сентябрь 16, 2014, 16:53 Задача такая: есть некая функция, написанная на С, изменять её нельзя. Функция циклически что-то делает, периодически вызывает хук extern "C" printmessage( char* msg ), выдавая так сообщения. И на каждом цикле проверяет extern "C" int on_stop, если там оказывается 1, то сбрасывает on_stop снова в 0 и прекращается.
В классе, наследующем QThread, в методе run() я запускаю эту функцию на выполнение. Для вывода сообщений хук выглядит вот так: Код: extern "C" void printmessage( char* msg ) и соответственно Код: void MyThread::ConsoleMessage( QString message ) поскольку прямо из С-функции сигнал послать нельзя а сигнал sigConsoleMessage( QString ) подключен таким образом: Код: connect( mythread, SIGNAL(sigConsoleMessage(QString)), pMainWindow, SLOT(slMessage(QString)), Qt::BlockingQueuedConnection); и для остановки глобальная переменная on_stop просто устанавливается в 1 где-то в MainWindow. Теперь чудеса - если заглушить содержимое MyThread::ConsoleMessage() чтобы сигнал не посылался и ничего не выводилось, то нить прекрасно завершается при взводе on_stop. Но если посылается сигнал sigConsoleMessage(QString) (слот slMessage(QString) выводит это сообщение куда надо), то стоит взвести on_stop, как сообщения перестают выводиться, но при этом... нить не завершается. Выяснил это, запустив после установки on_stop в главном приложении цикл Код: while( MyThread->isRunning() ) ...крутится до бесконечности и выводит running. :( Также пробовал подвесить слот на сигнал MyThread->finished() - слот не вызывается. То есть, нить почему-то не завершилась. Это заметно и в таск-менеджере - приложение продолжает кушать процессор. Что не так с передачей QString через блокирующее соединение? ЗЫ: заглушил содержимое MainWindow::slMessage(QString) но разрешил посылку в него sigConsoleMessage(QString) - косяк снова проявился. То есть, он не в приеме и выводе сообщения в окно, а именно из-за передачи QString сигналом из нити. Название: Re: Непонятная проблема с передачей QString из потока Отправлено: OKTA от Сентябрь 16, 2014, 17:02 Показывай код)
Название: Re: Непонятная проблема с передачей QString из потока Отправлено: Гурман от Сентябрь 16, 2014, 17:05 Всё, что можно, уже показал.
Название: Re: Непонятная проблема с передачей QString из потока Отправлено: OKTA от Сентябрь 16, 2014, 17:06 Ну а как хоть поток завершаешь?
Название: Re: Непонятная проблема с передачей QString из потока Отправлено: Гурман от Сентябрь 16, 2014, 17:09 Я же сказал - функция на С, когда обнаруживает on_stop, делает return обратно в run(). Всё. Никаких других принудительных завершений нет.
Есть один момент - С-поток находится в плагине, но это не должно иметь значения, по идее. Плагины превосходно работают и через другие сигнал-слот соединения общаются между собой и главным приложением. Название: Re: Непонятная проблема с передачей QString из потока Отправлено: OKTA от Сентябрь 16, 2014, 17:13 Ну если из run выходит, то должно по умолчанию завершаться. А если не завершается, то и не выходит получается :)
Цитировать void QThread::run () [virtual protected] The starting point for the thread. After calling start(), the newly created thread calls this function. The default implementation simply calls exec(). You can reimplement this function to facilitate advanced thread management. Returning from this method will end the execution of the thread. Название: Re: Непонятная проблема с передачей QString из потока Отправлено: Гурман от Сентябрь 16, 2014, 17:15 Да я как бы в курсе этого всего, не первый раз QThread использую. Но впервые столкнулся с тем, что передача из него QString через блокирующее соединение имеет такой эффект.
Название: Re: Непонятная проблема с передачей QString из потока Отправлено: Гурман от Сентябрь 16, 2014, 17:31 Да и дело в не QString... просто сигнал без параметров вызывает такой эффект. Никогда не было ничего подобного. Но впервые такой сигнал высылаю из нити, работающей в плагине.
Название: Re: Непонятная проблема с передачей QString из потока Отправлено: Igors от Сентябрь 16, 2014, 17:32 А что видно а отладчике? Чем кто занят в момент зависания? Если же пытаться угадать (др сейчас нет) то не ждет ли главная нитка на join? (QThread::wait)
Название: Re: Непонятная проблема с передачей QString из потока Отправлено: Гурман от Сентябрь 16, 2014, 17:49 Если оставить цикл ожидания завершения нити, то отладчик показывает, что приложение работает, пауза тормозит на строке inline void qt_noop() {} в qglobal.h. Если убрать ожидание, то приложение завершается по exit() - но нить то продолжала работать, её просто принудительно прибило.
Там фишка еще есть - перед выходом при on_stop С-функция вызывает еще один хук, функцию on_exit(), так вот она при таком завершении приложения не вызывается. А надо. Ощущение такое, будто при передаче сигнала где-то в QThread происходит ошибка, которая мешает нити не только нормально завершиться, но и даже продолжиться с какого-то момента. Название: Re: Непонятная проблема с передачей QString из потока Отправлено: Old от Сентябрь 16, 2014, 18:04 А не забиваете ли вы очередь событий событиями передачи сигнала? Да еще и ожидающими завершения выполнения слота.
Попробуйте посылать сигнал не каждый раз, а скажем каждые 100 или 1000 вызовов ConsoleMessage. Кстати, после установки on_stop в 1 вы дожидаетесь завершение рабочей нитки? Название: Re: Непонятная проблема с передачей QString из потока Отправлено: Гурман от Сентябрь 16, 2014, 18:24 Соединение Blocking. Это означает, что передающая нить ожидает, пока посланный в очередь сигнал не будет полностью обработан приемником до выхода из слота, как следует из документации. Только так и работает. Не вижу никакого смысла буферизовать сигнал руками, тем более, что я делал так, чтобы сообщение посылалось 1 раз в 5 секунд - ничего не менялось.
Про ожидаение - я же нарисовал в начале, что для проверки завершения крутится цикл, пока объект нити возвращает isRunning() - и он постоянно это возвращает. Увы, подвесить обработчик сигнала нити finished() в главном приложении нельзя - этот сигнал надо обработать в плагине, и иначе. Но он и там не вызывается... Что еще больше запутывает - если я инициирую завершение из самого плагина, то есть, устанавливаю on_stop в обработчике сигнала, высланного внутри плагина, то все срабатывает нормально. Но если этот обработчик вызывается по сигналу из главного приложения, то начинаются проблемы. Название: Re: Непонятная проблема с передачей QString из потока Отправлено: Igors от Сентябрь 16, 2014, 18:45 Если оставить цикл ожидания завершения нити, то отладчик показывает, что приложение работает, пауза тормозит на строке inline void qt_noop() {} в qglobal.h. Нормальный отладчик показывает все нитки - вот и смотрите по стеку где кто застрял. Ваша ситуация далеко не самая худшаяНазвание: Re: Непонятная проблема с передачей QString из потока Отправлено: Гурман от Сентябрь 16, 2014, 19:01 Пока нашел 1 косяк - сигнал finished() нити ловился двумя слотами, чего не должно быть. Очевидно, они интерферировали. Надо разбираться...
|