繁体   English   中英

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

[英]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.

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