Есть вопросы по реализации QThread в моем приложении?

Как было предложено в этом вопросе, сейчас я пытаюсь включить многопоточность.

Согласно ссылкам, предоставленным karlphillip, я понимаю, что документация о подклассах QThread не должна соблюдаться и использовать moveToThread() как объяснил. Теперь я вижу, что реализация QThread run() по умолчанию имеет только exec(), который затем должен быть завершен вызовом quit(), когда рабочий поток завершит операции. Теперь у меня есть несколько вопросов, чтобы я лучше понял:

QApplication* ptrApp=new QApplication(argc,argv);
QThread* th=new QThread;
MyClass* obj=new MyClass;
obj->moveToThread(th);
QObject::connect(th,SIGNAL(started()),obj,SLOT(someFunct()));
QObject::connect(obj,SIGNAL(over()),th,SLOT(quit()));
th->start();
//some GUI code in main thread here
return ptrApp->exec();
  1. Что произойдет, если я продолжу использовать someFunct() даже после того, как испущу over() из someFunct()? Это неопределенное поведение или нормальное?

  2. С каким потоком теперь будет связан obj (в то время как остальная часть кода после выдачи over() все еще выполняется в someFunct)? Насколько я понимаю, это не может быть в th, когда у меня есть quit() этот поток... quit() будет поставлен в очередь до тех пор, пока exec() в основном потоке не выполнит его, что приведет к выходу exec() в run() из th (надеюсь, я не делаю здесь ошибка). Я предполагаю, что ветка больше не существует.

  3. Как только слот quit() для th выполнен, можно ли предположить, что поток действительно завершился, или мне следует дополнительно подключить сигнал finished() th к некоторому слоту, чтобы быть абсолютно уверенным?


person ustulation    schedule 15.03.2012    source источник


Ответы (2)


  1. Не имеет значения, завершен ли цикл обработки событий, somefunct() будет продолжать работать до тех пор, пока не передаст управление ныне исчезнувшему циклу.

  2. #P2# <блочная цитата> #P3#
  3. quit() завершает цикл обработки событий, затем из потока выдается сигнал finished(), и поток завершается.
    Таким образом, даже когда вы получаете сигнал finished(), вы не должны предполагать, что поток еще не завершен. Вы можете использовать QThread::wait из основного потока после того, как получите этот сигнал, чтобы убедиться в этом.
    Если поток находится в завершающем состоянии, деструктор QThread уже вызывает wait, поэтому вы можете безопасно удалить поток после сигнала finished()deleteLater() еще безопаснее).

person alexisdm    schedule 16.03.2012
comment
спасибо 1. да, это поведение, которое я заметил... просто хотел убедиться, что оно не является неопределенным/незаконным или что-то в этом роде 2. хорошо... пожалуйста, скажите мне, что произойдет, если я удалю указатель QThread th (теперь, поскольку мы не можем перезапустить поток больше, я полагаю) 3. для quit() я понимаю, что он будет в очереди до тех пор, пока exec() в основном потоке не выполнит его ... но finished() - это сигнал, который не должен требовать никакого цикла событий, и это окончательный материал, который нужно сделать завершающим потоком, почему QThread::wait() требуется дополнительно, как вы указываете, когда я использую сигнал finished()? - person ustulation; 16.03.2012
comment
Для 2. вы можете останавливать и перезапускать поток так часто, как хотите. И для 3. испускания сигнала не требуется цикл обработки событий. Слот, к которому вы его подключаете, в любом случае должен находиться в другом потоке с работающим циклом событий (цикл событий потока не может получить свой собственный сигнал finish()). Но, просмотрев исходный код QThread, я думаю, что в большинстве случаев можно просто дождаться готового сигнала. - person alexisdm; 16.03.2012

1. Что произойдет, если я продолжу использовать someFunct() даже после того, как испущу over() из someFunct()? Это неопределенное поведение или нормальное?

Поскольку вы используете прямые соединения, испускание over вызовет непосредственно функцию quit, которая останавливает цикл обработки событий и возвращает результат из exec в методе запуска потока. Это означает, что someFunct() не завершит свое выполнение, а объекты внутри него либо утрачены, либо находятся в частично измененном состоянии.

2. С каким потоком теперь будет связан obj (в то время как остальная часть кода после вызова over() все еще выполняется в someFunct)?

Как было сказано ранее, somefunct не завершит свое выполнение. Но я считаю, что любые объекты, связанные с этим потоком, останутся таковыми. Я говорю, что верю, потому что нигде нет твердого утверждения, но в этом больше всего смысла. Как указано в документе, для отправки или получения этих объектов события поток должен быть запущен снова....

3. Как только слот quit() для th выполнен, можно ли предположить, что поток действительно завершился, или мне следует дополнительно подключить сигнал finish() th к некоторому слоту, чтобы быть абсолютно уверенным?

quit() завершает цикл обработки событий и возвращается туда, где был вызван exec().

Обратите внимание, что объект Qthread не является потоком. поэтому, пока вы не введете exec(), это основной поток, который выполняется... Так же как и основной поток, который выполняется после exec.

В любом случае, это отличные вопросы...

person UmNyobe    schedule 16.03.2012