我在GUI的主线程中运行了MainWindow对象,在它的构造函数中,我创建了一个新的worker对象和一个QThread对象,并且我将工作人员移动到线程,问题是当打印它们的in时,它们是相同的:
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怎么了?
发布于 2017-08-14 07:33:24
答:moveToThread 做工作,只是不像你想的那样。
看起来,在调用pc_w->moveToThread(t_pc)之后,您希望现在在t_pc中调用pc_w的所有成员函数。然而,这不是moveToThread()所做的。
moveToThread()的目的是更改QObject“线程亲和力”,或者换句话说,更改对象所在的线程。,但在基本级别上,它提供的一切只是保证在特定线程中调用(运行)所有对象s slots connected to any signal viaQt::QueuedConnection`。
成员函数仍然在您调用它们的线程中运行。在您的示例中,您可以从GUI线程调用initialize(),因此QThread::currentThreadId()给出了该线程的id。
我确实建议阅读螺纹亲和力上的官方文档和线程事件循环上的这篇文章。
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()”事件人为地放入线程事件循环中,达到了同样的效果。但是,它不执行任何编译时检查(“初始化”被指定为字符串)。
发布于 2017-08-10 07:18:05
尝试使用invokeMethod而不是轻率地调用pc_w->initialize(),例如:
QMetaObject::invokeMethod(pc_w, "initialize", Qt::QueuedConnection);在这种情况下,您的initialize()方法应该是时隙或信号。
https://stackoverflow.com/questions/45606648
复制相似问题