主线程无法从工作线程获取信号 [英] main thread cannot get signal form worker thread

查看:74
本文介绍了主线程无法从工作线程获取信号的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是主要的一部分.

此代码创建一个工作线程和一个工作线程.

This code create a worker and a workerthread.

工作线程被移动到工作线程.

The worker is moved to the workerthread.

然后工作人员正在等待要求其工作的信号.

The worker is then waiting for the signal to ask it to work.

当工作完成时,worker 发出一个带有结果的信号.

The worker emit a signal with result when job done.

main 应该捕获该信号并在 main 中初始化一个变量.

The main supposed to catch that signal and initialize a variable in the main.

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;
}

这是worker的doJob槽.

This is the doJob slot of the worker.

void worker::doJob()
{
    qDebug() << "worker::doJob invoked.";
    qDebug() << "worker Thread:" << QThread::currentThreadId();

    // Doing Job here

    emit jobDone(result);
}

这是qDebug的结果

It is the qDebug result

Main thread:  0x7ffff7fc6780
worker::doJob invoked.
worker Thread: 0x7fffdab44700

在调试模式下,我发现程序停在了workerThread.wait()永远不要去main::jobDone(int result).是什么原因?

In Debug mode, I find that the program is stop at workerThread.wait() and never go to main::jobDone(int result). What is the reason?

对主要代码稍作修改:

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() 上工作.

As long as signals supposed to invoke slots. That won't be working on wait() on the main thread that supposed to run the slot or specifically jobDone signal.

请务必了解 QThread::exec()QThread::wait() 在您的应用程序中.通常在真实的应用程序中,您的线程会循环(运行),而启动它的线程也在循环.该循环在受保护的 QThread::exec() 方法中实现.我们通常不需要显式调用 exec() 但我们需要允许线程运行.您可以通过使 main 函数使用 QEventLoop 进行循环来实现:

Make sure to understand the difference between QThread::exec() and QThread::wait() in your application. Normally in the real app your thread would be looping (running) while the thread that launched it is still looping as well. The loop is implemented in protected QThread::exec() method. We usually don't need to call exec() explicitly but we need to allow the thread to run. You can do that by making main function to use QEventLoop for looping:

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 为它.这是一个很好的 文章.所以它应该看起来像:

Instead you should create your own job object and do QObject::moveToThread for it. Here is a nice article about it. So it should rather look like:

connect(&workerThread, SIGNAL(started()), stupidTom, SLOT(doJob()));

我大概明白你为什么试图以上述方式运行线程.它类似于许多 C++ 示例.你也可以在 Qt 中做到这一点,但你还需要意识到你将如何等待 workerThread 的完成.Qt 最流行的线程间交互方式是使用信号和槽.这就是为什么我们应该在 main 中使用 QEventLoop.但当然还有另一种选择.对于较低级别的普通 C++,您可以使用互斥锁和条件变量来完成相同的操作.或者同样的 wait() 但不涉及任何信号.

I likely understand why you attempted to run the thread that way as above. It is similar to many C++ examples. You can also do that in Qt but you also need to realize how exactly you'll be waiting on completion of workerThread. And Qt most popular way to do the interaction between threads is with signals and slots. That is why we should use QEventLoop in main. But of course there is an alternative. For lower level plain C++ you can use mutex and condition variable to accomplish the same. Or that same wait() but then there is no signals involved.

还要注意调试输出,是否所有连接语句都将正确的信号连接到插槽.如果没有连接,它会打印警告.

Also watch the debug output, whether or not all the connect statements really connect proper signals to slots. In case if there is no connect it prints the warning.

这篇关于主线程无法从工作线程获取信号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆