[英]main thread cannot get signal form worker thread
这是主体的一部分。
此代码创建一个工作程序和一个工作线程。
工作程序已移至工作线程。
然后,工人正在等待信号要求其工作。
工作完成后,工人会发出信号并显示结果。
主机应捕获该信号并在主机中初始化变量。
main()
{.........
// This is the variable to be changed
variableToGetFromWorker = 0;
qDebug() << "Main thread: " << QThread::currentThreadId();
QThread workerThread;
worker* stupidTom = new stupidTom(number);
worker->moveToThread(&workerThread);
connect(&workerThread, &QThread::finished, &workerThread, &QObject::deleteLater);
connect(&workerThread, SIGNAL(start()), stupidTom, SLOT(doJob()));
connect(stupidTom, SIGNAL(jobDone(int)), this, SLOT(jobDone(int)));
workerThread.start();
workerThread.wait();
...........}
// This is a slot at main. Suppose to catch the signal from the worker
void main::jobDone(int result)
{
qDebug() << "Changing variable";
variableToGetFromWorker = result;
}
这是工作程序的doJob插槽。
void worker::doJob()
{
qDebug() << "worker::doJob invoked.";
qDebug() << "worker Thread:" << QThread::currentThreadId();
// Doing Job here
emit jobDone(result);
}
这是qDebug的结果
Main thread: 0x7ffff7fc6780
worker::doJob invoked.
worker Thread: 0x7fffdab44700
在调试模式下,我发现程序停止在workerThread.wait()
并且从不进入main::jobDone(int result)
。 是什么原因?
对主要代码进行少量编辑:
QThread workerThread;
worker* stupidTom = new stupidTom(number);
worker->moveToThread(&workerThread);
connect(&workerThread, &QThread::finished, &workerThread, &QObject::deleteLater);
connect(&workerThread, SIGNAL(started()), stupidTom, SLOT(doJob()));
connect(stupidTom, SIGNAL(jobDone(int)), this, SLOT(jobDone(int)));
connect(stupidTom, SIGNAL(jobDone(int)), &workerThread, SLOT(quit()));
workerThread.start();
workerThread.wait();
只要信号应该调用插槽即可。 那将不会在应该运行该插槽或主要是jobDone信号的主线程上的wait()
上起作用。
确保了解您的应用程序中的QThread :: exec()和QThread :: wait()之间的区别。 通常,在真实应用中,启动线程的线程也会循环(运行)。 该循环在受保护的QThread::exec()
方法中实现。 我们通常不需要显式调用exec()
但需要允许线程运行。 您可以通过使main函数使用QEventLoop进行循环来做到这一点:
int main()
{
//...
workerThread.start();
QEventLoop eventLoop;
// here you will probably want to hook-up QEventLoop::quit() slot
// to eventually quit the process
int returnCode = eventLoop.exec();
//...
return returnCode;
}
这也是错误的:
connect(&workerThread, SIGNAL(start()), stupidTom, SLOT(doJob()));
相反,您应该创建自己的作业对象并对其执行QObject :: moveToThread 。 这是一篇不错的文章 。 因此它应该看起来像:
connect(&workerThread, SIGNAL(started()), stupidTom, SLOT(doJob()));
我可能理解为什么您尝试如上所述那样运行线程。 它与许多C ++示例相似。 您也可以在Qt中做到这一点,但是您还需要意识到在workerThread完成之前您将等待多少时间。 Qt在线程之间进行交互的最流行方法是信号和插槽。 这就是为什么我们应该在main中使用QEventLoop的原因。 但是,当然还有另一种选择。 对于较低级别的普通C ++,您可以使用互斥量和条件变量来实现相同目的。 或相同的wait()
但不涉及任何信号。
还要观察调试输出,看是否所有的connect语句都确实将正确的信号连接到插槽。 如果没有连接,它将打印警告。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.