主线程无法从工作线程获取信号

时间:2015-11-15 05:23:12

标签: c++ multithreading qt

这是主要内容的一部分。

此代码创建一个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();

1 个答案:

答案 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}}但是没有涉及信号。

同时观察调试输出,无论所有连接语句是否真正将正确的信号连接到插槽。如果没有连接,则打印警告。