我有一个用于GUI的主线程,在其中运行MainWindow
对象,
在其构造函数中,我创建了一个新的工作程序对象和一个QThread
对象,然后将工作程序移至线程,问题是在打印其ID时它们是相同的:
MainWindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
std::cout<<"MAIN_ID "<< QThread::currentThreadId()<<std::endl;
QThread *t_pc = new QThread;
worker *pc_w;
pc_w = new pc_worker();
pc_w->moveToThread(t_pc);
t_pc->start();
pc_w->initialize();
// ...
}
worker.cpp
worker::worker(QObject *parent) : QObject(parent) {
}
void worker::initialize() {
std::cout << "INITIALIZE " << QThread::currentThreadId() << std::endl;
}
我得到:
MAIN_ID 0x7f4009ccb780
INITIALIZE 0x7f4009ccb780
怎么了?
最佳答案
答案:moveToThread
可以使正常工作,只是不符合您的预期。
看起来像在调用pc_w->moveToThread(t_pc)
之后,您希望现在在pc_w
中调用t_pc
的所有成员函数。但是,这不是moveToThread()
所做的。moveToThread()
的目的是更改QObject
的“线程相似性”,或者换句话说,就是对象所在的线程。 但是从根本上讲,它为您提供的所有功能只是确保通过Qt::QueuedConnection
连接到任何信号的所有对象的插槽都将在该特定线程中被调用(运行)。
成员函数仍在您从中调用它们的线程中运行。在您的情况下,您从GUI线程调用initialize()
,因此QThread::currentThreadId()
为您提供了该线程的ID。
我真的建议阅读有关线程事件循环的thread affinity和this article的官方文档。
QThread* thread = new QThread;
Worker* worker = new Worker;
// Uses Qt::AutoConnection (default)
// which will be transalted into Qt::QueuedConnection
QObject::connect(thread, &QThread::started, worker, &Worker::initialize);
std::cout<<"MAIN_ID "<< QThread::currentThreadId()<<std::endl;
worker->moveToThread(thread);
thread->start();
输出:
MAIN_ID 0000000000003E5C
INITIALIZE 0000000000003DAC
人工提出的解决方案 trivelt 将“call
initialize()
”事件放入线程事件循环中,以达到相同的效果。但是,它不执行任何编译时检查(将“initialize”指定为字符串)。