我有一个用于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 affinitythis 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”指定为字符串)。

10-07 13:26