这是主要内容的一部分。
此代码创建一个worker和一个workerthread。
工人被转移到了工作线上。
然后工人正在等待信号要求它工作。
工作完成后,工作人员会发出结果信号。
主要应该捕获该信号并初始化主要变量。
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();
答案 0 :(得分:2)
只要信号应该调用插槽。这将不会在QThread::exec()
上对应该运行插槽的主线程或特定的jobDone信号起作用。
确保了解应用中QThread::exec()和QThread::wait()之间的区别。通常在真实应用程序中,您的线程将循环(运行),而启动它的线程仍然循环。循环以受保护的exec()
方法实现。我们通常不需要显式调用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;
}
,但我们需要允许线程运行。您可以通过使main函数使用QEventLoop进行循环来实现:
connect(&workerThread, SIGNAL(start()), stupidTom, SLOT(doJob()));
这也是错误的:
connect(&workerThread, SIGNAL(started()), stupidTom, SLOT(doJob()));
相反,您应该创建自己的工作对象并为其执行QObject::moveToThread。关于它,这是一个很好的article。所以它应该看起来像:
wait()
我可能理解为什么你试图像上面那样运行线程。它类似于许多C ++示例。你也可以在Qt中做到这一点,但你也需要意识到你将如何等待完成workerThread。而Qt最流行的线程之间的交互方式是信号和插槽。这就是为什么我们应该在main中使用QEventLoop。但当然还有另一种选择。对于较低级别的普通C ++,您可以使用互斥和条件变量来完成相同的操作。或者那个{{1}}但是没有涉及信号。
同时观察调试输出,无论所有连接语句是否真正将正确的信号连接到插槽。如果没有连接,则打印警告。