简体   繁体   English

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

[英]main thread cannot get signal form worker thread

This is part of the main. 这是主体的一部分。

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. 然后,工人正在等待信号要求其工作。

The worker emit a signal with result when job done. 工作完成后,工人会发出信号并显示结果。

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

This is the doJob slot of the worker. 这是工作程序的doJob插槽。

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

    // Doing Job here

    emit jobDone(result);
}

It is the qDebug result 这是qDebug的结果

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

In Debug mode, I find that the program is stop at workerThread.wait() and never go to main::jobDone(int result) . 在调试模式下,我发现程序停止在workerThread.wait()并且从不进入main::jobDone(int result) What is the reason? 是什么原因?

Little editing on the main code: 对主要代码进行少量编辑:

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();

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. 那将不会在应该运行该插槽或主要是jobDone信号的主线程上的wait()上起作用。

Make sure to understand the difference between QThread::exec() and QThread::wait() in your application. 确保了解您的应用程序中的QThread :: exec()QThread :: wait()之间的区别。 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. 该循环在受保护的QThread::exec()方法中实现。 We usually don't need to call exec() explicitly but we need to allow the thread to run. 我们通常不需要显式调用exec()但需要允许线程运行。 You can do that by making main function to use QEventLoop for looping: 您可以通过使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;
}

And this is also wrong: 这也是错误的:

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

Instead you should create your own job object and do QObject::moveToThread for it. 相反,您应该创建自己的作业对象并对其执行QObject :: moveToThread Here is a nice article about it. 这是一篇不错的文章 So it should rather look like: 因此它应该看起来像:

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

I likely understand why you attempted to run the thread that way as above. 我可能理解为什么您尝试如上所述那样运行线程。 It is similar to many C++ examples. 它与许多C ++示例相似。 You can also do that in Qt but you also need to realize how exactly you'll be waiting on completion of workerThread. 您也可以在Qt中做到这一点,但是您还需要意识到在workerThread完成之前您将等待多少时间。 And Qt most popular way to do the interaction between threads is with signals and slots. Qt在线程之间进行交互的最流行方法是信号和插槽。 That is why we should use QEventLoop in main. 这就是为什么我们应该在main中使用QEventLoop的原因。 But of course there is an alternative. 但是,当然还有另一种选择。 For lower level plain C++ you can use mutex and condition variable to accomplish the same. 对于较低级别的普通C ++,您可以使用互斥量和条件变量来实现相同目的。 Or that same wait() but then there is no signals involved. 或相同的wait()但不涉及任何信号。

Also watch the debug output, whether or not all the connect statements really connect proper signals to slots. 还要观察调试输出,看是否所有的connect语句都确实将正确的信号连接到插槽。 In case if there is no connect it prints the warning. 如果没有连接,它将打印警告。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM