У меня есть класс ParentThread
полученный из QThread
со следующим методом run()
который выглядит примерно так:
void ParentThread::run()
{
QThread *childThread = new QThread;
QObject::connect(childThread, SIGNAL(finished()), this, SLOT(onChildThreadFinished());
QObject::connect(childThread, SIGNAL(finished()), childThread, SLOT(deleteLater());
childThread->start();
exec();
}
Слот onChildThreadFinished()
определен в ParentThread
и должен работать в контексте ParentThread
. Однако, используя приведенный выше код, onChildThreadFinished
только onChildThreadFinished
если соединение сигнал/слот является Qt::DirectConnection
, но затем выполняется в контексте дочернего потока. В случае, если соединение сигнал/слот определяется как Qt::QueuedConnection
, слот никогда не Qt::QueuedConnection
. Я использую Qt 4.8.5. Подумайте, в чем проблема?
Вы указываете, что слот onChildThreadFinished() определен в ParentThread и должен работать в контексте ParentThread. Это предположение неверно. Это одна из причин, почему подкласс QThread
не рекомендуется.
Если вы хотите использовать слоты в ваших потоках, подклассификация QThread
- это не то, что вы хотите сделать. Вместо этого используйте метод "рабочий объект". Подкласс QObject
и вызов QObject::moveToThread
чтобы переместить объект в новый поток.
Вот что говорят Qt об этом:
Важно помнить, что экземпляр QThread находится в старом потоке, который его создавал, а не в новом потоке, который вызывает run(). Это означает, что все слоты в очереди QThread будут выполняться в старом потоке. Таким образом, разработчик, который хочет вызывать слоты в новом потоке, должен использовать подход "рабочий-объект"; новые слоты не должны быть реализованы непосредственно в подклассу QThread.
finished
deleteLater
вызывается первыйdeleteLater
который является прямым соединением, а объектchildThread
удаляется, когда элемент управления возвращается в цикл обработки событий. ПоэтомуonChildThreadFinished
неonChildThreadFinished
, когда объект-эмиттер уничтожен.