[英]QThread moveToThread doesn't work
I've a main thread for the GUI, in which is run the MainWindow
object, in its constructor I create a new worker object and a QThread
object and the i move the worker to the thread, the problem is that when printing their ids they are the same: 我有一个用于GUI的主线程,在其中运行
MainWindow
对象,在其构造函数中创建一个新的工作程序对象和一个QThread
对象,然后将工作程序移至该线程,问题是在打印其ID时,是相同的:
MainWindow.cpp 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.cpp
worker::worker(QObject *parent) : QObject(parent) {
}
void worker::initialize() {
std::cout << "INITIALIZE " << QThread::currentThreadId() << std::endl;
}
I get: 我得到:
MAIN_ID 0x7f4009ccb780
INITIALIZE 0x7f4009ccb780
What's wrong? 怎么了?
Answer: moveToThread
does work, just not in the way you expected. 答:
moveToThread
确实可以正常工作,但并非您所期望的那样。
Looks like after calling pc_w->moveToThread(t_pc)
you expected all member functions of pc_w
to be called in t_pc
now. 貌似打完电话后
pc_w->moveToThread(t_pc)
你所期望的所有成员函数pc_w
在被称为t_pc
现在。 However, that is not what moveToThread()
does. 但是,那不是
moveToThread()
所做的。
The purpose of moveToThread()
is to change QObject
"thread affinity" or in other words thread where an object lives. moveToThread()
的目的是更改QObject
“线程相似性”,换句话说,就是更改对象所在的线程。 But on the basic level everything it gives you is just the guarantee that all the object`s slots connected to any signal via Qt::QueuedConnection
will be invoked (run) in that particular thread. 但是从根本上讲,它所提供的一切只是保证通过
Qt::QueuedConnection
连接到任何信号的所有对象的插槽Qt::QueuedConnection
将在该特定线程中被调用 (运行)。
Member functions still run in the thread you invoke them from. 成员函数仍在您从中调用它们的线程中运行。 In your case, you call
initialize()
from the GUI thread, so QThread::currentThreadId()
gives you the id of that thread. 在您的情况下,您从GUI线程调用
initialize()
,因此QThread::currentThreadId()
为您提供该线程的ID 。
I really recommend to read official doc on thread affinity and this article on thread event loops. 我真的建议阅读有关线程相似性的官方文档,以及有关线程事件循环的这篇文章 。
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();
Output: 输出:
MAIN_ID 0000000000003E5C
INITIALIZE 0000000000003DAC
The solution trivelt proposed artificially puts "call initialize()
" event into the thread event loop reaching the same effect. trivelt提出的解决方案是人为地将“ call
initialize()
”事件放入线程事件循环中,从而达到相同的效果。 However, it does not perform any compile-time checks ("initialize" is specified as a string). 但是,它不执行任何编译时检查(将“ initialize”指定为字符串)。
Try to use invokeMethod
instead of diretly calling pc_w->initialize()
, eg: 尝试使用
invokeMethod
而不是直接调用pc_w->initialize()
,例如:
QMetaObject::invokeMethod(pc_w, "initialize", Qt::QueuedConnection);
Your initialize()
method should be SLOT or SIGNAL in this case. 在这种情况下,您的
initialize()
方法应为SLOT或SIGNAL。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.