我尝试将https://wiki.qt.io/QThreads_general_usage 中的一种方法与 moveToThread 结合使用。一切安好。但是如果我尝试将参数添加到完成的信号中,则会出现以下问题:
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);
}
主要类是:
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();
}
如果我将这个完成的信号连接到某个插槽(slotFinished),我就没有收到这个插槽的调用。
这是信号/插槽/moveToThread 的预期行为吗?
问题是元数据信息。
当您在信号和槽之间进行默认连接并且当信号从分配给接收器的不同线程发出时,Qt 会执行魔术并包装信号的参数(创建副本)并将它们排在目标线程的事件循环中。
然后当目标线程执行 Qt 事件循环的逻辑时,值被解包,并使用复制的值调用相应的插槽。
现在为了能够进行这个复制,Qt 必须对这种类型有一些基本的了解。因此,当您使用 Qt 类型时,它将开箱即用,但是您使用外部类型(例如std::string
在您的情况下),您必须首先执行类型注册。
所以基本上你的代码缺少这样的东西:
// to be declared somewhere
Q_DECLARE_METATYPE(std::string);
// to be invoked at the beginning of program
qRegisterMetaType<std::string>();
如果没有类型注册,Qt 不知道如何进行复制并在日志中提供警告。检查 Qt 日志我确定它会提示您正确的错误消息。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句