2016-08-09 2 views
1

J'essaie d'utiliser Qthread avec un objet. A cet effet, ce code est écrit:que se passe-t-il si je n'utilise pas deletelater pour supprimer qthread?

QThread *thread1 = new QThread(); 
serialclass *obje = new serialclass(); 
void MainWindow::on_pushButton_baglan_clicked() 
{ 
    obje->moveToThread(thread1); 
    connect(thread1,SIGNAL(started()),obje,SLOT(baglan()), Qt::UniqueConnection); 
    connect(obje,SIGNAL(finished()),thread1,SLOT(quit())); //end of the baglan function finished() signal is emitted. 
    thread1->start(); 
} 

Mon code fonctionne. Mais j'ai utilisé quit(), pas deletelater(). Le bouton peut être poussé beaucoup de temps. La première question est: cette méthode est-elle vraie? Ma deuxième question est ce qui se passe si j'appuie sur le bouton beaucoup de temps. Y a-t-il beaucoup de fil? Est-ce que chaque fois un thread est créé?

Répondre

0

C'est très bien. Vous devriez comprendre ce que vous faites et pourquoi: le code et son but devraient venir de vous et d'une telle compréhension.

Lorsque vous appuyez sur le bouton d'un grand nombre de fois, l'application peut être dans l'un des deux états:

  1. Le fil est déjà terminé: obje->thread() == nullptr et vous êtes redémarrer le fil - il fonctionne très bien . Le thread est toujours en cours d'exécution: obje->thread() == thread1 et moveToThread et thread1->start() ne font rien.

Hélas, il ne sert à rien d'arrêter le thread. Il a une boucle d'événement qui est bloquée jusqu'à l'arrivée de nouveaux événements, ce n'est pas comme si un QThread n'utilisait aucun CPU. Démarrer un thread coûte cher: il crée un nouveau thread natif. Un thread fini cesse d'exister: oui, vous avez toujours un QThread, mais c'est comme avoir un handle pour un fichier fermé. QThread est une poignée de thread, après tout.

Vous devriez garder vos membres par valeur, pas par pointeur - ceci évite la pessimisation prématurée bête de l'indirection supplémentaire via un point. Vous pouvez configurer toutes les connexions à l'avance. Vous n'avez pas besoin de l'emplacement on_pushButton_baglan_clicked(): vous pouvez connecter le bouton-poussoir directement à l'instance SerialClass. Vous devez également utiliser une classe dérivée QThread qui peut être détruite en toute sécurité.

Votre code peut ressembler à ceci. Le compilateur va générer un destructeur de désaffectation des ressources pour vous. C'est le travail du compilateur, et il ne vous manquera jamais dans ce travail - alors qu'un développeur humain est très enclin à l'échec. Ainsi, vous devez tirer parti RAII à votre parti, car il se déplace un travail manuel serviles sur la machine qui le fera parfaitement et pour rien :)

// MyWindow.h 
#include <QMainWindow> 
#include <QThread> 
#include "SerialClass.h" 
#include "ui_MyWindow.h" 

class MyWindow : public QMainWindow { 
    Q_OBJECT 
    class SafeThread : public QThread { 
    using QThread::run; // final 
    public: 
    ~SafeThread() { quit(); wait(); } 
    } m_serialThread; 
    SerialClass m_serial; 
    Ui::MyWindow ui; 
public: 
    MyWindow(QWidget * parent = nullptr); 
}; 

// MyWindow.cpp 
#include "MyWindow.h" 

MyWindow::MyWindow(QWidget * parent) : 
    QMainWindow{this} 
{ 
    ui.setupUi(this); 
    connect(ui.pushButton_baglan, &QPushButton::clicked, 
      &m_serial, &SerialClass::baglan); 
    m_serial.moveToThread(&m_serialThread); 
    m_serialThread.start(); 
} 

Si vous ne voulez pas tous les détails de mise en œuvre à vivre dans MyWindow en-tête, vous should use a PIMPL.