我尝试使用来自 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 的预期行为吗?
最佳答案
问题是元数据信息。
当你做 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 日志,我确定它会提示您正确的错误消息。
关于c++ - Qt moveToThread,带参数的信号/槽,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51822393/