Название: Главный поток умирает по непонятной причине. Отправлено: White Owl от Февраль 12, 2010, 21:43 Играюсь с QThread:
main.cpp: Код: void sleep(int msec) { MyThread.h Код: #ifndef MYTHREAD_H Код: #include "MyThread.h" Если запустить этот код как есть (то есть без создания объекта QApplication), то на выходе я получаю: Debug: main started Warning: QEventLoop: Cannot be used without QApplication Debug: thread started Debug: 0 ..... много строк Debug: 0 Debug: 5 ..... много строк Debug: 5 Debug: 10 ..... много строк Debug: 10 Debug: thread finished Debug: main finished А если первой командой в main() создавать объек QApplication, то я получаю на выходе всего три строки: Debug: main started Debug: thread started Debug: 0 Спрашивается: что происходит? Что я делаю неправильно? Как правильно использовать QEventLoop? Название: Re: Главный поток умирает по непонятной причине. Отправлено: lit-uriy от Февраль 12, 2010, 22:21 >>emit t.setI(200);
Зачем пишешь слово "emit" в функции main? Название: Re: Главный поток умирает по непонятной причине. Отправлено: lit-uriy от Февраль 12, 2010, 22:24 >>А если первой командой в main() создавать объек QApplication, то я получаю на выходе всего три строки:
А запуск цикла событий: app.exec() где? Название: Re: Главный поток умирает по непонятной причине. Отправлено: SABROG от Февраль 12, 2010, 22:31 Юрий, я думаю тут несколько сложнее ситуация. emit сам по себе пустышка, лишь указатель типа тут мы вызываем слот или испускаем сигнал. Другое дело, что слот вызывается не объекта, который находится в другом потоке, поэтому вызов t.setI() всегда будет DirectConnect, как прямой callback. Сам экземпляр класса MyThread тоже принадлежит главному потоку, также как и i и QEventLoop.
С помощью метод eventLoop.processEvents(); автор пытается обрабатывать события. Но их там быть не может по определению. А раз их там нет, то я не понимаю откуда тут deadlock, если processEvents() по умолчанию не ждет поступления каких либо событий, а должен возвращаться сразу же обратно, если очередь пуста. С вариантом когда нет QApplication я еще могу понять почему всё работает. Скорее всего потому, что processEvents() не найдя действующей инстанции QCoreApplication просто возвращается, а прямые вызовы t.setI() делают своё черное дело. Т.е. очередь никак не задействована. --- В общем как обычно. Проверил код у себя программа ведет себя одинаково при QApplication и его отсутствии за одним исключением. Если есть QApplication/QCoreApplication, то программа просто остается висеть в памяти после сообщения: Код: main finished А именно сразу после return 0; Название: Re: Главный поток умирает по непонятной причине. Отправлено: White Owl от Февраль 12, 2010, 23:02 ... Читал, думал... ничего не понял.Не, я кажется понял что происходит, но не понял как это исправить. Есть где-нибудь простенький пример как надо правильно создавать фоновые потоки чтобы они работали как сервер? Чтоб оно висело в ждущем режиме, главный поток давал запрос и оставался рисовать ГУИ, фоновый поток проделав долгую операцию кидал результаты главному потоку и засыпал. В общем как обычно. Проверил код у себя программа ведет себя одинаково при QApplication и его отсутствии за одним исключением. Если есть QApplication/QCoreApplication, то программа просто остается висеть в памяти после сообщения: А у меня она в памяти висеть не остается... Играюсь с 4.6.1 на Виндах.Код: main finished А именно сразу после return 0; Название: Re: Главный поток умирает по непонятной причине. Отправлено: SABROG от Февраль 12, 2010, 23:13 В общем я вырубил Mass Effect 2 (программа стала нормально выходить) и проверил твой пример еще раз - поведение одинаковое как с QApplication так и без. Всё выводится в консоль и работает. Но как я уже говорил тут сплошной прямой вызов, никаких сигналов и слотов через эвенты не передается.
Название: Re: Главный поток умирает по непонятной причине. Отправлено: White Owl от Февраль 13, 2010, 00:21 Ok... я уже понял что наврал в своем тесте на полную катушку. Но все таки мой главный вопрос остается пока без ответа:
Есть где-нибудь простенький пример как надо правильно создавать фоновый поток чтобы он работал как сервер? Фоновый поток должен висеть в ждущем режиме, главный поток будет посылать запрос (или набор запросов в очередь) и рисовать ГУИ, фоновый поток проделав долгую операцию кидал результаты главному потоку и засыпал. Название: Re: Главный поток умирает по непонятной причине. Отправлено: ax от Февраль 13, 2010, 00:56 Сам обьект MyThread со своими переменными находиться в потоке главном потоке QApplication.
Вставь в конструкторе MyThread Код: moveToThread(this) Название: Re: Главный поток умирает по непонятной причине. Отправлено: lit-uriy от Февраль 13, 2010, 01:33 Цитировать Другое дело, что слот вызывается не объекта, который находится в другом потоке, поэтому вызов t.setI() всегда будет DirectConnect, как прямой callback. В данной ситуации слот следует воспринимать как вызов обычной функции-члена класса, и только. А emit применительно к слоту вообще несуразица.Название: Re: Главный поток умирает по непонятной причине. Отправлено: White Owl от Февраль 13, 2010, 01:52 Сам обьект MyThread со своими переменными находиться в потоке главном потоке QApplication. Вставил. Получил:Вставь в конструкторе MyThread Код: moveToThread(this) main started thread started 0 ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread. Current thread 22ff30. Receiver ' ' (of type 'QCoreApplication') was created in thread 3e27a8", file kernel\qcoreapplication.cpp, line 347 Название: Re: Главный поток умирает по непонятной причине. Отправлено: SABROG от Февраль 13, 2010, 03:50 Тебе нужно создавать сигнал или делать реализацию на основе эвентов. Запись "emit slot()" бессмысленна, она работает как обычная функция и ничего в очередь не ставит. Если нужно вызвать слот без сигнала через очередь, то пользуйся QMetaObject::invokeMethod().
Название: Re: Главный поток умирает по непонятной причине. Отправлено: mcrads от Февраль 13, 2010, 15:51 как делал я. я передавал в конструктор потока параметры из главного потока которые необходимо изменить. далее я значения этих параметров присваивал внутренним переменным потока, работал с ними. потом вызывал передачу значений опять в параметры и останавливал поток из себя.
Если не ошибаюсь, передачу параметров можно сделать так же обращением parent.parametr = ... в случае если ты задашь тип родительского объекта не QObject а свой изначальный и опишешь параметры как публичные. Такой метод у меня тоже работал вполне сносно. потоки позволяют много чего. реализация QEventLoop считаю вообще здесь ни к чему. поиграйся. и не забывай про отладку по шагам =) Название: Re: Главный поток умирает по непонятной причине. Отправлено: Igors от Февраль 15, 2010, 04:50 реализация QEventLoop считаю вообще здесь ни к чему. Да вот как раз "к чему" :) Слот/сигнал между нитками выполняется только через eventLoop. И QDirectConnection тоже. Примерно таким образом:- посылающий в др. нитку никак не может ее "остановить", поэтому он посылает событие в очередь этой нитки. Если QDirectConnection установлен, то посылающий ждет на семафоре пока событие будет обработано. Когда это случится - зависит от нитки-приемника, если она игнорирует свой eventLoop - то никогда. С точки зрения посылающего все правильно, QDirectConnection есть синхронный способ: послал - получил ответ - продолжил выполнение. Так что все eventLoop должны быть запущены Название: Re: Главный поток умирает по непонятной причине. Отправлено: White Owl от Февраль 15, 2010, 21:16 Вот, нашел в сети такую статью и там даже есть пример.
http://www.linuxjournal.com/article/9602 Кажется все мои вопросы про создание фоновых потоков изображающих сервер отвечены. В FAQ ee! В FAQ! :) Осталось только понять как объект может принадлежать потоку, и зачем это собственно говоря делается? Вроде ж у всех нитей одного процесса общая память и только стеки разные? Или аналогия с fork()/CreateThread() в QThread не играет? |