QThread moveToThread不起作用

时间:2017-08-10 07:02:55

标签: c++ multithreading qt qthread

我有一个GUI的主线程,其中运行MainWindow对象, 在它的构造函数中,我创建了一个新的worker对象和一个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

怎么了?

2 个答案:

答案 0 :(得分:2)

答案: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”指定为字符串)。

答案 1 :(得分:0)

尝试使用invokeMethod代替直接调用pc_w->initialize(),例如:

QMetaObject::invokeMethod(pc_w, "initialize", Qt::QueuedConnection);

在这种情况下,您的initialize()方法应为SLOT或SIGNAL。