我尝试使用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是预期的行为吗?
答案 0 :(得分:2)
问题是元数据信息。
当您在信号和插槽之间执行default connection时,并且当信号从与接收者所分配的线程不同的线程发出时,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日志,我确定它会提示您正确的错误消息。