简体   繁体   English

Qt moveToThread,带有参数的信号/插槽

[英]Qt moveToThread, signals/slots with arguments

I've tried to use an approach from https://wiki.qt.io/QThreads_general_usage with moveToThread. 我尝试通过moveToThread使用https://wiki.qt.io/QThreads_general_usage中的方法。 Everything is fine. 一切顺利。 But if I try to add the argument to the finished signal, there is the following problem: 但是,如果我尝试将参数添加到完成的信号中,则会出现以下问题:

class Worker : public QObject {
Q_OBJECT
public:
   Worker();
   ~Worker();
public slots:
   void process();
signals:
   void finished(const std::string& value);
};

void Worker::process() { // Process. Start processing data.
    // allocate resources using new here
    qDebug("Hello World!");
    std::string s = someFunctionReturningString(); 
    emit finished(s);
}

The main class is: 主要类别是:

class Main: public QObject {
Q_OBJECT
public:
    void startProgram();
public slots:
   void slotFinished(const std::string& s);
};

void Main::startProgram() {
   QThread* thread = new QThread;
   Worker* worker = new Worker();
   worker->moveToThread(thread);
   connect(thread, &QThread::started, worker, &Worker::process);
   connect(worker, &Worker::finished, thread, &QThread::quit);
   connect(worker, &Worker::finished, worker, &Worker::deleteLater);
   connect(worker, &Worker::finished, this,   &Main::slotFinished);
   connect(thread, &QThread::finished, thread, &QThread::deleteLater);
   thread->start();
}

void Main::slotFinished(const std::string& value) {
    qDebug() << "result " << value.c_str();
}

If I connect this finished signal to some slot (slotFinished), I didn't get the call of this slot. 如果我将完成的信号连接到某个插槽(slotFinished),则不会接到该插槽的电话。

Is it an expected behavior of the signals/slots/moveToThread? 是信号/插槽/ moveToThread的预期行为吗?

Problem is meta data information. 问题是元数据信息。

When you do a default connection between signal and slot and when signal is emitted from different thread than receiver is assigned to, Qt does a magic and wraps arguments for signal (creates a copy) and queue them in event loop of destination thread. 当您在信号和插槽之间建立默认连接 ,并且当信号从与接收者分配给的线程不同的线程发出时,Qt发挥了魔力,并包装了信号的参数(创建副本)并将它们放在目标线程的事件循环中。

Then when destination tread executes logic of the Qt event loop, values are unwrapped and respective slot is invoked with copied values. 然后,当目标暂存区执行Qt事件循环的逻辑时,将解包值,并使用复制的值调用相应的插槽。

Now to be able to do this copy, Qt has to have some minimal knowledge about that type. 为了能够进行此复制,Qt必须对这种类型有一些最低的了解。 So when you use Qt types it will work out of the box, but you use external types like std::string in your case, you have to first perform type registration. 因此,当您使用Qt类型时,它可以立即使用,但是如果您使用的是外部类型(如std::string ,则必须首先执行类型注册。

So basically your code is missing something like this: 所以基本上您的代码缺少这样的事情:

// to be declared somewhere
Q_DECLARE_METATYPE(std::string);

// to be invoked at the beginning of program
qRegisterMetaType<std::string>();

Without type registration Qt doesn't know how to do a copy and provides a warning in logs. 如果没有类型注册,Qt将不知道如何进行复制,并且会在日志中提供警告。 Check Qt logs I'm sure it prompts you with proper error message. 检查Qt日志,我确定它会提示您正确的错误消息。

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

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