2017-08-10 93 views
0

我有一个主线程的图形用户界面,在其中运行是MainWindow对象, 在其构造函数创建一个新的工作对象和QThread对象和工人的我移动到线程,问题是,他们的打印ID时,它们是相同的:QThread的moveToThread不起作用

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 

有什么不对?

+0

但是,当通过连接SLOT/SIGNAL调用工人类时,打印的ID不同 –

+2

当您直接调用函数时,它将在您调用它的线程中运行。 – thuga

+0

将initialize()定义为插槽并从MainWindow发出信号。像这样连接它们:connect(this,SIGNAL(signal_initialize()),pc_w,SLOT(initialize()),Qt :: QueuedConnection); –

回答

0

尝试使用invokeMethod,而不是直接写给调用pc_w->initialize(),例如:

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

initialize()方法应该是在这种情况下SLOT或信号。

1

答案:moveToThread确实工作,只是不符合你的预期。

看起来像在致电pc_w->moveToThread(t_pc)之后,您预计现在可以在t_pc中调用pc_w的所有成员函数。但是,这不是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提出人为地把 “呼initialize()” 事件到线程事件循环达到同样的效果。但是,它不执行任何编译时检查(“初始化”被指定为字符串)。