2015-11-21 6 views
0

У меня возникли проблемы с потоковой обработкой Qt, чтобы позволить потоковой части обновлять графический интерфейс моей программы. Похоже, что это известная «проблема» с Qt, поэтому я нашел несколько учебников, но я не понимаю, почему мой пример здесь не работает.QThread с слотами и сигналами, похоже, не создает новый поток

я унаследовал от 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 просто замерзает, и все, что я могу сделать, это CTRL + C на терминале. Итак, я думаю, что мой capture_loop, который является бесконечным циклом на данный момент, блокирует программу, а это значит, что мой поток не запущен.

Но я назвал thread-> start(). Я даже попытался запустить поток в конструкторе CaptureThread, вызвав this-> start(), но результат тот же.

Любая идея?

ответ

1

Ваш использование QThread неправильный. Просто создав поток, он не будет выполняться в потоке. вам нужно будет сделать это внутри функции QThread::run (переопределив ее), так как это единственный, который будет работать в новом потоке. Обратите внимание, что как только вы вернетесь из этой функции, поток исчезнет.

Если вы хотите использовать собственный цикл внутри функции QThread::run (вместо этого, используя цикл событий по умолчанию Qts), поток не сможет получать сигналы внутри функции запуска!

Вот пример того, как использовать 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 
    } 
    } 
}; 
+0

Спасибо, что это прекрасно работает. Но я поставил свою петлю внутри метода run, так, как вы сказали, мой поток больше не может получать сигнал. Чтобы остановить мой цикл, я действительно использую thread-> terminate(), это опасно? Я полагаю, что мой метод getPacket может работать над чем-то, убивая поток. – Charrette

+0

Да, это так! Прекращение потока - это необязательная вещь (не каждая система поддерживает ее) и может привести к неопределенному состоянию. Вы должны использовать bool для синхронизации. Создайте функцию, которая устанавливает ее в true/false и проверяет ваш цикл – Felix

Смежные вопросы