簡體   English   中英

為什么我不能在信號上啟動 QThread?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM