2013-03-05 32 views
8

私はStackOverflowの新機能で、これが正しいかどうか疑問に思っています。Qtを使用した単純なマルチスレッド:これは正しいのですか?

私はマルチスレッドをテストするための簡単なQtアプリケーションを作成しています。ウィジェットを含むMainWindowと、QThreadをサブクラス化してrun()メソッドをオーバーライドするMyThreadクラスを作成しました。

アプリケーションには、「カウンタの開始」と「カウンタの停止」の2つのボタンと、テキストフィールドが表示されます。 「カウンタを開始」を押すと、ワーカースレッドが作成され、バックグラウンドで実行され、whileループでカウンタを連続的にインクリメントし、メインスレッド(GUIがある場合)に更新値を通知します。 "Stop Counter"を押すと、whileループを止めるメインスレッドに信号が送られ、 "Start Counter"が再び押されるまでカウンタが停止します。

これは完全に問題なく動作しますが、これが最善の方法ですか?私はこれで新しく、 "QThreadをサブクラス化しないでください"と言う人や、 "サブクラスQThread"と言っている人をたくさん読んでいます。ちょっと混乱します。これが(バックグラウンドスレッドで「開始」ボタンと「停止」ボタンを使用して計算集約型ループを実行する)この種の処理を実装する最善の方法ではない場合、私が間違っているとすれば、どうやってそれを正しくするのですか?私は間違ったやり方を学びたくありません。

ありがとうございました!そして、ここのコードです:

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

は '睡眠(1/1000)は' ''睡眠(0)を意味注意してくださいだけで罰金になります。 – deepmax

+0

@M M.良いキャッチ – Throwback1986

+0

良いキャッチ、ありがとう!それを睡眠に変えた(0.001)。 – evdc

答えて

4

時間QThreadのサブクラス化のほとんどはQtの中でスレッドを実行する間違った方法です。 article about threads, event loops and otherを読むと、より良い方法でQtでスレッドを使用する方法がわかります。しかし、QThreadを使う唯一の正しい方法があると主張する人は耳を傾けないでください。 2つの方法がありますが、サブクラス化は一般的には必要ない場合もありますが、時には役立つこともあります。サブクラス化が必要になるまで、サブクラス化しない方法を使用するだけです。あなたの特別なケースでは、サブクラス化は必要ありません。

+1

それでは、サブクラス化? (なぜ、私はそれを使用する必要はありませんか?)別のQThreadと別のワーカースレッドを作成してからmoveToThread()を実行するよりもはるかに簡単です。少なくとも、サブクラス化を使用するときは、何が起こっているのかを理解することがはるかに簡単です。 –

+0

@ GijsvanOort、上記の記事はあなたの質問に答えます。 – ixSci

1

msleep(100);物事をsleep(1/1000);を交換しては:)

関連する問題