带有插槽和信号的QThread似乎不会创建新的线程

QThread with slots and signals does not seem to create a new thread

本文关键字:创建 线程 QThread 插槽 信号      更新时间:2023-10-16

我在Qt线程方面遇到了一些问题,以允许线程部分更新程序的GUI。这似乎是Qt的一个已知"问题",所以我找到了多个教程,但我不明白为什么我的例子不起作用。

我从QThread继承如下:

class CaptureThread: public QThread {
  Q_OBJECT
public:
  CaptureThread(const QObject *handler, QPushButton *start) {
    CaptureThread::connect(start, SIGNAL(clicked()), this, SLOT(capture_loop()));
    CaptureThread::connect(this, SIGNAL(sendPacket(Packet*)),
                           this, SLOT(receivePacket(Packet*)));
  }
signals:
  void sendPacket(Packet*);
public slots:
  void capture_loop() {
    Packet *packet;
    while (my_condition) {
      packet = Somewhere::getPacket();
      //getPacket is define somewhere and is working fine                                
      emit(sendPacket(packet));
      std::cout << "Sending packet!" << std::endl;
    }
  }
};

这是CaptureHandler:

class CaptureHandler: public QWidget {
  Q_OBJECT
public:
  CaptureHandler() {
    start = new QPushButton("Capture", this);
    thread = new CaptureThread(this, start);
    thread->start();
  }
public slots:
  void  receivePacket(Packet *packet) {
    std::cout << "Packet received!" << std::endl;
    /*                                                                                   
      Here playing with layout etc...                                                    
     */
  }
private:
  QPushButton   *start;
  CaptureThread *thread;
};

我认为信号和插槽还可以,因为它显示在终端上

Sending packet!
Packet received!
Sending packet!
Packet received!
Sending packet!
Packet received!

但在receivePacket插槽中,我试图修改GUI,但它不起作用。GUI刚刚冻结,我所能做的就是在终端上按CTRL+C。所以我认为我的capture_loop,目前是一个无限循环,正在阻塞程序,这意味着我的线程还没有启动。

但我调用了thread->start()。我甚至试图通过调用this->start()在CaptureThread构造函数中启动线程,但结果是一样的。

知道吗?

您使用QThread错误。只要创建线程,它就不会在线程上执行。您需要在QThread::run函数中(通过重写它)执行此操作,因为这是唯一一个将在新线程上运行的函数。请注意,一旦您从该函数返回,线程就会退出。

如果您想在QThread::run函数中使用自己的循环(而不是使用Qts默认事件循环),线程将无法在run函数中接收信号!

这里有一个关于如何使用QThread:的例子

class CaptureThread: public QThread {
  Q_OBJECT
public:
  CaptureThread(const QObject *handler, QPushButton *start) {
     //calling "start" will automatically run the `run` function on the new thread
     CaptureThread::connect(start, SIGNAL(clicked()), this, SLOT(start()));
    //use queued connection, this way the slot will be executed on the handlers thread
    CaptureThread::connect(this, SIGNAL(sendPacket(Packet*)),
                           handler, SLOT(receivePacket(Packet*)), Qt::QueuedConnection);
  }
signals:
  void sendPacket(Packet*);
protected:
  void run() {
    Packet *packet;
    while (my_condition) {
      packet = Somewhere::getPacket();
      //getPacket is define somewhere and is working fine                                
      emit sendPacket(packet) ;//emit is not a function
      qDebug() << "Sending packet!";//you can use qDebug
    }
  }
};