【问题标题】:Qt C++ - How to pass data from a worker thread to main thread?Qt C++ - 如何将数据从工作线程传递到主线程?
【发布时间】:2018-01-30 17:17:13
【问题描述】:

我正在尝试在 Qt (C++) 中执行线程间通信。我有一个工作线程进行一些计算,我希望工作线程在完成后将其结果返回到主线程。因此我使用了一个连接,由于调试,我知道信号已成功发出,但它是未执行的插槽,我不明白为什么。

相关代码:

webcamClass::webcamClass(QObject *parent) : QObject(parent)
{  
    workerThread = new QThread(this);
    workerClassObj = new workerClass();

    //connect for image
    connect(workerClassObj, SIGNAL(mySignal(QPixmap)), this, SLOT(mySlot(QPixmap)));
     //connect(&workerClassObj, workerClass::mySignal(QPixmap), this, webcamClass::mySlot(QPixmap));


    connect( workerThread, SIGNAL(started()), workerClassObj, SLOT(getImage()) );
    workerClassObj->moveToThread(workerThread);


}

void webcamClass:: foo()
{

      workerThread->start();
}

void workerClass::getImage()
{
    qint64 successFailWrite;
    QImage img;
    QPixmap pixmap;

    ... do some stuff with pixmap...

    qDebug()<<"going to emit result";

    emit mySignal(pixmap);

    qDebug()<<"emitted";
}


void webcamClass::mySlot(QPixmap p)
{qDebug()<<"this message should be displayed"; }

对应的头文件:

   class workerClass : public QObject
    {
        Q_OBJECT
    private:

    public:
        explicit workerClass(QObject *parent = nullptr);


    signals:
        void mySignal(QPixmap);
    };



webcamClass::webcamClass(QObject *parent) : QObject(parent)
{
    Q_OBJECT
public:
    explicit webcamClass(QObject *parent = nullptr);

public slots:
    void mySlot(QPixmap p);

private:

    QThread *workerThread;
    workerClass *workerClassObj;


};

上面的代码只是输出:

going to emit result
emitted

但不幸的是没有输出this message should be displayed

webcamClass 属于父线程,而 workerClass 属于 - 你猜对了 - 工作线程。

有人可以解释如何设置我的连接以触发 mySlot() 吗?

谢谢!

【问题讨论】:

  • 你试过移动 connect(workerClassObj, SIGNAL(mySignal(QPixmap)), this, SLOT(mySlot(QPixmap)));在 moveToThread 调用之前?顺便说一句,如果您使用 qt5,您最好使用新的信号/插槽连接 (wiki.qt.io/New_Signal_Slot_Syntax)
  • 您是否使用signals: 声明了mySignal
  • @AMA 更新了我的帖子
  • @JLev 我知道新语法,你可以看到它就在那里,就在 cmets 的下面一行。是的,我尝试在 moveToThread 之前移动它,结果相同
  • 你在哪里打电话给webcamClass::foo()?此外,您对新信号/插槽语法的尝试似乎不正确。

标签: c++ multithreading qt


【解决方案1】:

在您粘贴到 pastebin.com/UpPfrNEt 的代码中,您有一个使用 while (1)getVideoFrame 方法。如果调用此方法,它会一直运行并阻止事件循环处理信号。您可以通过多种方式解决它,我认为最佳做法是将 while(1) 替换为其他方法。

【讨论】:

  • @LandonZeKepitelOfGreytBritn -- 这不仅仅是删除while 循环的情况。接收排队信号的线程必须有一个活动的Qt事件循环。
  • 您可以尝试在循环中添加QApplication::processEvents()
  • 我会接受你的回答,它指出了我没有考虑过的一个方面,以及我在任何一种情况下都会面临的问题。我的代码中的实际错误与拼写错误有关...谢谢。
【解决方案2】:

如果可能,我强烈建议您使用新的 Signal Slot 语法:

connect( SOURCEINSTANCE, &amp;CLASS::SIGNAL, TARGETINSTANCE, &amp;CLASS::SLOT );

在你的情况下,可能是:

connect( workerClassObj, &amp;workerClass::mySignal, this, &amp;webcamClass::mySlot );

具体来说,如果你想在线程之间传递信号和插槽,你必须小心。首先,检查 connect 调用的连接类型,它实际上是最后一个参数。

connect( workerClassObj, &amp;workerClass::mySignal, this, &amp;webcamClass::mySlot, Qt::QueuedConnection );

详细解释请看这里: http://doc.qt.io/qt-5/signalsandslots.html

如果你想传递自定义类型,你必须先将它们声明为元类型。 添加例如this 在你的构造函数中:

qRegisterMetaType("MyDataType");

请确保您的自定义数据类型具有默认构造函数,并注意不能跨线程传递引用。

【讨论】:

  • 尝试新语法给我invalid use of non-static member function 'void workerClassObj::mySignal(QPixmap)'
  • 你能发布你使用的代码吗?我很确定你忘记了'&'
  • 试试这个:connect(recognitionClObj, &recognitionClass::signPixMapLandmarks, this, &webcamClass::emitUpdateGuiLandmarks, Qt::QueuedConnection);
  • 您是否应该发出 signPixMapLandmarks 而不是 gotVideoFrame?
  • 您能否将您的主帖更新为实际代码?其他人可以更轻松地提供帮助
猜你喜欢
  • 2021-08-15
  • 2019-12-26
  • 2014-08-04
  • 2011-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-31
相关资源
最近更新 更多