![](/img/trans.png)
[英]Why can't I call QMetaObject::invokeMethod(&threadObj, &QThread::start, Qt::QueuedConnection)?
[英]Why can't I start a QThread on a signal?
我想在另一個啟動時啟動一個 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();
工人.h
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 相關 function
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 重現 OPs 問題(只是有點短)。
#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();
}
Output:
Qt Version: 5.13.0
Start "worker 1"
這是OP觀察到的。 所以呢?
worker1.qThread.started
信號連接到worker2.start
槽worker1
已啟動worker2
似乎沒有啟動。 是什么讓我懷疑: moveToThread()
。
目的是將Worker
object 與其成員QThread
相關聯。
我不確定的是:在QThread
啟動之前這可能嗎?
為了檢查這一點,我評論了moveToThread()
:
Worker(const QString &name): name(name)
{
//moveToThread(&qThread);
connect(&qThread, &QThread::finished, this, &Worker::reportFinished);
}
Output:
Qt Version: 5.13.0
Start "worker 1"
Start "worker 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();
}
Output:
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.
獎金問題:
那么這是否意味着“QThread::start”作為信號的接收者是無用的?
不,這不對。 即使沒有具有該簽名的現有信號(我知道),應用程序開發人員也可以自由地“發明”一個。
但是,請記住 Qt5 實際上並不需要明確標記的SLOT
將它們用於信號,過去可能會找到更明顯的答案:
使用 Qt4 信號, QThread::start
槽可以直接連接到QThread::started
信號。 (此時QThread::start
中唯一參數的默認值生效。)
由於我沒有使用 Qt4 信號的經驗(我從 Qt5 開始),我修改了我的示例代碼以證明我是對的:
QObject::connect(&worker1.qThread, SIGNAL(started()), &worker2.qThread, SLOT(start()));
Output:
Qt Version: 5.13.0
Start "worker 1"
"worker 1" associated to its thread, from now.
"worker 2" associated to its thread, from now.
現在,當worker1.started()
worker2.qThread.start()
時,不再發出Start "worker 2"
。
因此,使用 Qt4 信號,OP 的原始代碼可能已經工作。 不是信號和槽的不兼容(正如有人猜測的那樣)導致了這個問題,但可能是上面描述的moveToThread()
問題(以及)並沒有讓它令人滿意地工作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.