2013-03-05 16 views
8

Sono nuovo per StackOverflow e mi chiedo se sto facendo bene:Semplice multithreading con Qt: sto facendo bene?

Sto scrivendo una semplice applicazione Qt per testare multi-threading (qualcosa che sono anche completamente nuovo a). Ho creato una MainWindow che contiene widget e una classe MyThread che sottoclasse QThread e sostituisce il metodo run().

L'applicazione visualizza semplicemente due pulsanti, "Contatore inizio" e "Contatore stop" e un campo di testo. Quando viene premuto "start counter", viene creato un thread worker che viene eseguito in background, incrementando continuamente un contatore in un ciclo while e segnalando il thread principale (dove si trova la GUI) con il valore aggiornato. Quando viene premuto "Stop Counter", viene inviato un segnale al thread principale che interrompe il ciclo while e il contatore viene arrestato finché non viene premuto nuovamente "Start Counter".

Questo funziona perfettamente bene ... ma è il modo migliore? Sono nuovo in questo, e leggo molte persone che dicono "non sottoclasse QThread" e altre persone che dicono "sottoclasse QThread", ed è un po 'confuso. Se questo non è il modo migliore per implementare questo tipo di cose (esegui un ciclo intensivo dal punto di vista computazionale in un thread in background con i pulsanti "start" e "stop"), che cos'è? Se sto sbagliando, come faccio a farlo bene? Non voglio imparare la strada sbagliata.

Grazie! Ed ecco il codice:

MyThread.h

#ifndef MYTHREAD_H 
#define MYTHREAD_H 

#include <QThread> 
#include <QMutex> 

class MyThread : public QThread 
{ 
    Q_OBJECT 

public slots: 
    void stopRunning(); 

protected: 
    virtual void run(); 

signals: 
    void signalValueUpdated(QString); 

private: 
    bool isRunning; 

}; 

MyThread.cpp

#include "MyThread.h" 
#include <QString> 

void MyThread::run() 
{ 
    qDebug("Thread id inside run %d",(int)QThread::currentThreadId()); 

    static int value=0; //If this is not static, then it is reset to 0 every time this function is called. 
    isRunning = 1; 
    while(isRunning == 1) 
    { 
     QString string = QString("value: %1").arg(value++); 
     sleep(1/1000); //If this isn't here, the counter increments way too fast and dies, or something; the app freezes, anyway. 

     emit signalValueUpdated(string);  
    }    
} 

void MyThread::stopRunning() 
{ 
    isRunning = 0; 
} 

MainWindow.h

#ifndef MAINWINDOW_H 
#define MAINWINDOW_H 

#include <QApplication> 
#include <QPushButton> 
#include <QHBoxLayout> 
#include <QLineEdit> 
#include "MyThread.h" 

class MainWindow : public QWidget 
{ 
    Q_OBJECT 

    public: 
    MainWindow(QWidget *parent = 0); 

    private: 
    //Widgets 
    QHBoxLayout * boxLayout; 
    QPushButton * startButton; 
    QPushButton * stopButton; 
    QLineEdit * lineEdit; 

    MyThread thread; 
}; 

#endif 

mainwindow.cpp

#include "MainWindow.h" 

MainWindow::MainWindow(QWidget *parent) : QWidget(parent) 
{ 
    boxLayout = new QHBoxLayout(this); 
    startButton = new QPushButton("Start Counter", this); 
    stopButton = new QPushButton("Stop Counter", this); 
    lineEdit = new QLineEdit(this); 

    boxLayout->addWidget(startButton); 
    boxLayout->addWidget(stopButton); 
    boxLayout->addWidget(lineEdit); 

    qDebug("Thread id %d",(int)QThread::currentThreadId()); 

    //When the start button is pressed, invoke the start() method in the counter thread 
    QObject::connect(startButton,SIGNAL(clicked()),&thread,SLOT(start()), Qt::QueuedConnection); 

    //When the stop button is pressed, invoke the stop() method in the counter thread 
    QObject::connect(stopButton,SIGNAL(clicked()),&thread,SLOT(stopRunning()), Qt::QueuedConnection); 

    //When the counter thread emits a signal saying its value has been updated, reflect that change in the lineEdit field. 
    QObject::connect(&thread,SIGNAL(signalValueUpdated(const QString&)),lineEdit,SLOT(setText(const QString&)), Qt::QueuedConnection); 
} 
+1

Fare attenzione 'sonno (1/1000)' 'significa sonno (0)'. – deepmax

+0

@M M. Buona cattura – Throwback1986

+0

Buona cattura, grazie! Modificato per dormire (0.001). – evdc

risposta

4

maggior parte del tempo QThread sub-classing è un modo sbagliato di fare filettatura in Qt. Ti suggerisco di leggere uno article about threads, event loops and other che potrebbe darti un'idea di come usare i thread in Qt in un modo migliore. Ma non ascoltare chi sostiene che esiste l'unico modo giusto per usare QThread. Ci sono 2 modi e, mentre la sottoclasse non è necessaria in generale, potrebbe essere utile a volte. Devi solo usare un modo non sottoclasse fino a quando non hai davvero bisogno di sottoclasse. Nel tuo caso particolare non hai bisogno di sottoclassi.

+1

Quindi, qual è esattamente il _sviluppo_ di usare sottoclassi? (cioè, perché dovrei _non_ usarlo?) Mi sembra che sia molto più facile che creare un QThread separato e un thread di lavoro separato e quindi fare moveToThread(). Almeno, quando si utilizza la sottoclasse, è molto più facile capire cosa sta succedendo. –

+0

@GijsvanOort, l'articolo sopra menzionato risponde alla tua domanda. – ixSci

1

Sostituire sleep(1/1000); con msleep(100); le cose andranno bene :)

Problemi correlati