2013-03-05 46 views
8

我是新来的StackOverflow,并想知道我是否正在做这件事:简单的多线程与Qt:我做对了吗?

我正在写一个简单的Qt应用程序来测试多线程(我也是全新的东西)。我制作了一个包含小部件的MainWindow,以及一个MyThread类,该类继承了QThread并覆盖了run()方法。

应用程序只显示两个按钮,“启动计数器”和“停止计数器”,以及一个文本字段。当按下“启动计数器”时,将创建一个工作线程并在后台运行,在一个while循环中连续增加一个计数器并用更新的值向主线程(GUI所在的位置)发送信号。当按下“停止计数器”时,一个信号被发送到停止while循环的主线程,并且计数器停止直到再次按下“启动计数器”。

这工作得很好......但这是最好的方法吗?我是这个新手,并且读了很多人说“不要继承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 2013-03-05 05:13:07

+0

@M M.好赶上 – Throwback1986 2013-03-05 05:28:02

+0

好,赶快,谢谢!改变它睡觉(0.001)。 – evdc 2013-03-05 05:37:16

回答

4

大部分时间QThread的子类是一种错误的方法做线程Qt中。我建议你阅读一个article about threads, event loops and other这可以让你知道如何更好地使用Qt中的线程。但是不要听任何人争论说只有一种正确的方式来使用QThread。有两种方法,而子类化通常不需要,有时候可能有用。你只需要使用非子类方法,直到你真的需要子类。在你的特定情况下,你不需要子类化。

+1

那么,究竟是什么_disadvantage_使用子类? (即为什么我不应该使用它?)在我看来,它比创建单独的QThread和单独的工作线程然后执行moveToThread()更容易。至少,在使用子类时,理解发生的事情要容易得多。 – 2013-06-04 08:32:26

+0

@GijsvanOort,我上面提到的文章回答你的问题。 – ixSci 2013-06-04 09:19:20

1

更换sleep(1/1000);msleep(100);事情会就好:)