我想在另一个启动时启动QThread,但是它不起作用。
main.cpp片段
Worker stat_worker;
stat_worker.moveToThread(stat_worker.stat_thread);
Worker some;
some.moveToThread(some.somethread);
QObject::connect(stat_worker.stat_thread, SIGNAL(started()), some.somethread, SLOT(start()));
QObject::connect(some.somethread, SIGNAL(started()), &some, SLOT(print_some()));
stat_worker.stat_thread->start();
worker class Worker : public QObject
{
Q_OBJECT
public:
explicit Worker();
QThread *stat_thread = new QThread;
QThread *somethread = new QThread;
signals:
//some signals
void start_thread();
public slots:
//some slots
void print_some();
void somethread_starter();
};
#endif // WORKER_H
worker.cpp相关功能void Worker::print_some()
{
qInfo() << "-somethread started() signal arrived!";
}
当我尝试通过单击按钮启动线程时,也没有用。甚至创建一个启动线程的插槽:
QObject::connect(stat_worker.stat_thread, &QThread::started, &some, &Worker::somethread_starter);
void Worker::somethread_starter()
{
qInfo() << "-I got started by another thread!";
somethread->start();
}
或在启动另一个线程时发出的信号:void Worker::wip_status(){
emit start_thread();
}
QObject::connect(stat_worker.stat_thread, &QThread::started, &stat_worker, &Worker::wip_status);
QObject::connect(&stat_worker, &Worker::start_thread, &some, &Worker::somethread_starter);
工作。在此先感谢您回复我的帖子。
最佳答案
我试图用自己的MCVE(只是短一点)重现OP的问题。
#include <QtWidgets>
struct Worker: QObject {
QString name;
QThread qThread;
Worker(const QString &name): name(name)
{
moveToThread(&qThread);
connect(&qThread, &QThread::finished, this, &Worker::reportFinished);
}
void start()
{
qDebug() << "Start" << name;
qThread.start();
}
void reportFinished()
{
qDebug() << "Exit" << name;
}
};
// main application
int main(int argc, char **argv)
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
QCoreApplication app(argc, argv);
Worker worker1("worker 1");
Worker worker2("worker 2");
// install signal handlers
QObject::connect(&worker1.qThread, &QThread::started, &worker2, &Worker::start);
worker1.start();
// runtime loop
return app.exec();
}
输出:Qt Version: 5.13.0
Start "worker 1"
这是OP观察到的。所以呢?worker1.qThread.started
信号连接到worker2.start
插槽worker1
已启动worker2
似乎没有开始。 是什么让我感到怀疑:
moveToThread()
。目的是将
Worker
对象与其成员QThread
相关联。我不确定的是:在启动
QThread
之前有可能吗?为了检查这一点,我评论了
moveToThread()
: Worker(const QString &name): name(name)
{
//moveToThread(&qThread);
connect(&qThread, &QThread::finished, this, &Worker::reportFinished);
}
输出:Qt Version: 5.13.0
Start "worker 1"
Start "worker 2"
我之所以评论moveToThread()
的原因:qThread::start()
的调用应在主应用程序(线程)的上下文中进行。因此,将
worker2
移至其QThread
意味着该信号已发送到worker2.qThread
的事件循环-实际上尚未启动。因此,该事件无法处理。
moveToThread()
应该稍后执行-例如在started()
信号的 react 中:#include <QtWidgets>
struct Worker: QObject {
QString name;
QThread qThread;
Worker(const QString &name): name(name)
{
connect(&qThread, &QThread::started, this, &Worker::moveThisToThread);
connect(&qThread, &QThread::finished, this, &Worker::reportFinished);
}
void start()
{
qDebug() << "Start" << name;
qThread.start();
}
void moveThisToThread()
{
moveToThread(&qThread);
qDebug() << name << "associated to its thread, from now.";
}
void reportFinished()
{
qDebug() << "Exit" << name;
}
};
// main application
int main(int argc, char **argv)
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
QCoreApplication app(argc, argv);
Worker worker1("worker 1");
Worker worker2("worker 2");
// install signal handlers
QObject::connect(&worker1.qThread, &QThread::started, &worker2, &Worker::start);
worker1.start();
// runtime loop
return app.exec();
}
输出:Qt Version: 5.13.0
Start "worker 1"
"worker 1" associated to its thread, from now.
Start "worker 2"
"worker 2" associated to its thread, from now.
奖励问题:
So does that mean "QThread::start" is useless as receiver of a signal?
不,这不对。即使不存在带有该签名的信号(我知道),应用程序开发人员也可以“发明”一个信号。
但是,请记住,Qt5实际上并不需要显式标记的
SLOT
来将它们用于信号,过去可能会找到一个更明显的答案:对于Qt4信号,可以将
QThread::start
插槽直接连接到QThread::started
信号。 (然后QThread::start
中唯一的一个参数的默认值生效。)由于我没有使用Qt4信号的经验(我从Qt5开始),因此我修改了示例代码以证明自己是正确的:
QObject::connect(&worker1.qThread, SIGNAL(started()), &worker2.qThread, SLOT(start()));
输出:Qt Version: 5.13.0
Start "worker 1"
"worker 1" associated to its thread, from now.
"worker 2" associated to its thread, from now.
由于Start "worker 2"
现在直接调用worker1.started()
,因此不再发出worker2.qThread.start()
。因此,使用Qt4信号可能已经运行了OP的原始代码。
引起问题的不是信号和插槽的不兼容(有人猜到了),但上述
moveToThread()
问题(也可能)并没有使它令人满意地工作。
关于c++ - 为什么我不能在信号上启动QThread?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63067960/