Russian Qt Forum
Ноябрь 26, 2024, 09:14 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Непонятная проблема с передачей QString из потока  (Прочитано 6561 раз)
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« : Сентябрь 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 )
{
    mythread->ConsoleMessage( mythread::tr(msg) );
}


и соответственно

Код:
void MyThread::ConsoleMessage( QString message )
{
emit sigConsoleMessage( 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() )
        qDebug() << "running";

...крутится до бесконечности и выводит running.  Грустный Также пробовал подвесить слот на сигнал MyThread->finished() - слот не вызывается. То есть, нить почему-то не завершилась. Это заметно и в таск-менеджере - приложение продолжает кушать процессор.

Что не так с передачей QString через блокирующее соединение?

ЗЫ: заглушил содержимое MainWindow::slMessage(QString) но разрешил посылку в него sigConsoleMessage(QString) - косяк снова проявился. То есть, он не в приеме и выводе сообщения в окно, а именно из-за передачи QString сигналом из нити.
« Последнее редактирование: Сентябрь 16, 2014, 17:04 от Гурман » Записан

2^7-1 == 127, задумайтесь...
OKTA
Гость
« Ответ #1 : Сентябрь 16, 2014, 17:02 »

Показывай код)
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #2 : Сентябрь 16, 2014, 17:05 »

Всё, что можно, уже показал.
Записан

2^7-1 == 127, задумайтесь...
OKTA
Гость
« Ответ #3 : Сентябрь 16, 2014, 17:06 »

Ну а как хоть поток завершаешь?
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #4 : Сентябрь 16, 2014, 17:09 »

Я же сказал - функция на С, когда обнаруживает on_stop, делает return обратно в run(). Всё. Никаких других принудительных завершений нет.

Есть один момент - С-поток находится в плагине, но это не должно иметь значения, по идее. Плагины превосходно работают и через другие сигнал-слот соединения общаются между собой и главным приложением.
« Последнее редактирование: Сентябрь 16, 2014, 17:13 от Гурман » Записан

2^7-1 == 127, задумайтесь...
OKTA
Гость
« Ответ #5 : Сентябрь 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.
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #6 : Сентябрь 16, 2014, 17:15 »

Да я как бы в курсе этого всего, не первый раз QThread использую. Но впервые столкнулся с тем, что передача из него QString через блокирующее соединение имеет такой эффект.
Записан

2^7-1 == 127, задумайтесь...
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #7 : Сентябрь 16, 2014, 17:31 »

Да и дело в не QString... просто сигнал без параметров вызывает такой эффект. Никогда не было ничего подобного. Но впервые такой сигнал высылаю из нити, работающей в плагине.
Записан

2^7-1 == 127, задумайтесь...
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #8 : Сентябрь 16, 2014, 17:32 »

А что видно а отладчике? Чем кто занят в момент зависания? Если же пытаться угадать (др сейчас нет) то не ждет ли главная нитка на join? (QThread::wait)
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #9 : Сентябрь 16, 2014, 17:49 »

Если оставить цикл ожидания завершения нити, то отладчик показывает, что приложение работает, пауза тормозит на строке inline void qt_noop() {} в qglobal.h. Если убрать ожидание, то приложение завершается по exit() - но нить то продолжала работать, её просто принудительно прибило.

Там фишка еще есть - перед выходом при on_stop С-функция вызывает еще один хук, функцию on_exit(), так вот она при таком завершении приложения не вызывается. А надо.

Ощущение такое, будто при передаче сигнала где-то в QThread происходит ошибка, которая мешает нити не только нормально завершиться, но и даже продолжиться с какого-то момента.
Записан

2^7-1 == 127, задумайтесь...
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #10 : Сентябрь 16, 2014, 18:04 »

А не забиваете ли вы очередь событий событиями передачи сигнала? Да еще и ожидающими завершения выполнения слота.
Попробуйте посылать сигнал не каждый раз, а скажем каждые 100 или 1000 вызовов ConsoleMessage.

Кстати, после установки on_stop в 1 вы дожидаетесь завершение рабочей нитки?
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #11 : Сентябрь 16, 2014, 18:24 »

Соединение Blocking. Это означает, что передающая нить ожидает, пока посланный в очередь сигнал не будет полностью обработан приемником до выхода из слота, как следует из документации. Только так и работает. Не вижу никакого смысла буферизовать сигнал руками, тем более, что я делал так, чтобы сообщение посылалось 1 раз в 5 секунд - ничего не менялось.

Про ожидаение - я же нарисовал в начале, что для проверки завершения крутится цикл, пока объект нити возвращает isRunning() - и он постоянно это возвращает. Увы, подвесить обработчик сигнала нити finished() в главном приложении нельзя - этот сигнал надо обработать в плагине, и иначе. Но он и там не вызывается...

Что еще больше запутывает - если я инициирую завершение из самого плагина, то есть, устанавливаю on_stop в обработчике сигнала, высланного внутри плагина, то все срабатывает нормально. Но если этот обработчик вызывается по сигналу из главного приложения, то начинаются проблемы.

Записан

2^7-1 == 127, задумайтесь...
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #12 : Сентябрь 16, 2014, 18:45 »

Если оставить цикл ожидания завершения нити, то отладчик показывает, что приложение работает, пауза тормозит на строке inline void qt_noop() {} в qglobal.h.
Нормальный отладчик показывает все нитки - вот и смотрите по стеку где кто застрял. Ваша ситуация далеко не самая худшая
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #13 : Сентябрь 16, 2014, 19:01 »

Пока нашел 1 косяк - сигнал finished() нити ловился двумя слотами, чего не должно быть. Очевидно, они интерферировали. Надо разбираться...
Записан

2^7-1 == 127, задумайтесь...
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.206 секунд. Запросов: 23.