C++ 为什么可以';我不能在信号上启动QThread吗?
我想在另一个QThread启动时启动一个QThread,但它不工作 main.cpp代码段C++ 为什么可以';我不能在信号上启动QThread吗?,c++,multithreading,qt,signals-slots,qthread,C++,Multithreading,Qt,Signals Slots,Qthread,我想在另一个QThread启动时启动一个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(
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();
工人
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!";
}
工作
提前感谢您回复我的帖子。我试图用我自己的MCVE重现OPs问题(只是稍微短一点) 这是OP观察到的。那么,什么
信号连接到worker1.qThread.start
插槽worker2.start
已启动worker1
似乎没有启动worker2
moveToThread()
其目的是将Worker
对象与其成员QThread
关联
我不确定的是:在QThread
启动之前,这可能吗
为了验证这一点,我对moveToThread()
进行了注释:
输出:
Qt版本:5.13.0
启动“工人1”
启动“工人2”
我对moveToThread()
进行注释的原因如下:
调用qThread::start()
应该在主应用程序(线程)的上下文中进行。
因此,将worker2
移动到其QThread
意味着信号被发送到worker2.QThread
的事件循环,而该循环实际上尚未启动
因此,无法处理该事件
moveToThread()
应稍后执行–例如,在响应started()
信号时:
#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();
}
奖金问题: 那么,这是否意味着“QThread::start”作为信号接收器是无用的呢 不,不是。即使不存在具有该签名的现有信号(我知道),应用程序开发人员也可以自由地“发明”一个 但是,请记住Qt5实际上并不需要明确标记的
插槽
s来将其用于信号,在过去可能会找到一个更明显的答案:
使用Qt4信号时,QThread::start
插槽可以直接连接到QThread::start
信号。(此时,QThread::start
中唯一一个参数的默认值生效。)
由于我没有Qt4信号的经验(我从Qt5开始),我修改了我的示例代码以证明我是正确的:
QObject::connect(&worker1.qThread, SIGNAL(started()), &worker2.qThread, SLOT(start()));
输出:
Qt版本:5.13.0
启动“工人1”
“工作线程1”与其线程关联,从现在开始。
“worker 2”与其线程关联,从现在开始。
现在,Start“worker 2”
不再作为worker1.Start()
直接调用worker2.qThread.Start()
发出
因此,使用Qt4信号,OP的原始代码可能已经工作。
不是信号和插槽的不兼容(有人猜测)导致了这个问题,可能是上面描述的
moveToThread()
问题(以及)使它不能令人满意地工作。我试图用我自己的MCVE重现OPs问题(只是稍微短一点)
这是OP观察到的。那么,什么
信号连接到worker1.qThread.start
插槽worker2.start
已启动worker1
似乎没有启动worker2
moveToThread()
其目的是将Worker
对象与其成员QThread
关联
我不确定的是:在QThread
启动之前,这可能吗
为了验证这一点,我对moveToThread()
进行了注释:
输出:
Qt版本:5.13.0
启动“工人1”
启动“工人2”
我对moveToThread()
进行注释的原因如下:
调用qThread::start()
应该在主应用程序(线程)的上下文中进行。
因此,将worker2
移动到其QThread
意味着信号被发送到worker2.QThread
的事件循环,而该循环实际上尚未启动
因此,无法处理该事件
moveToThread()
应稍后执行–例如,在响应started()
信号时:
#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();
}
奖金问题: 那么,这是否意味着“QThread::start”作为信号接收器是无用的呢 不,不是。即使不存在具有该签名的现有信号(我知道),应用程序开发人员也可以自由地“发明”一个 但是,请记住Qt5实际上并不需要明确标记的
插槽
s来将其用于信号,在过去可能会找到一个更明显的答案:
使用Qt4信号时,QThread::start
插槽可以直接连接到QThread::start
信号。(此时,QThread::start
中唯一一个参数的默认值生效。)
由于我没有Qt4信号的经验(我从Qt5开始),我修改了我的示例代码以证明我是正确的:
QObject::connect(&worker1.qThread, SIGNAL(started()), &worker2.qThread, SLOT(start()));
输出:
Qt版本:5.13.0
启动“工人1”
“工作线程1”与其线程关联,从现在开始。
“worker 2”与其线程关联,从现在开始。
现在,Start“worker 2”
不再作为worker1.Start()
直接调用worker2.qThread.Start()
发出
因此,使用Qt4信号,OP的原始代码可能已经工作。
问题的原因不是信号和插槽的不兼容(有人猜测),而是上面描述的moveToThread()
问题(也有可能),它的工作不令人满意。如果使用,当插槽的签名不匹配时,会出现编译时错误。因此,您不会在“应用程序输出”中看到它们,而是在“构建输出”中看到它们,甚至无法启动应用程序。这与运行前无法检测到不匹配插槽的旧Qt信号相反。因此,应尽可能首选Qt5信号
#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();
}
QObject::connect(&worker1.qThread, SIGNAL(started()), &worker2.qThread, SLOT(start()));