2013-03-05 24 views
8

Tôi mới sử dụng StackOverflow và tự hỏi mình có đang làm điều này không:Đa luồng đơn giản với Qt: tôi có làm điều này đúng không?

Tôi đang viết một ứng dụng Qt đơn giản để kiểm tra đa luồng (thứ tôi cũng hoàn toàn mới). Tôi đã tạo một MainWindow chứa các widget và một lớp MyThread để phân lớp QThread và ghi đè phương thức run().

Ứng dụng chỉ hiển thị hai nút, "Bộ đếm bắt đầu" và "Bộ đếm dừng" và trường văn bản. Khi "bắt đầu truy cập" được nhấn, một chuỗi công nhân được tạo và chạy ở chế độ nền, liên tục tăng bộ đếm trong một vòng lặp while và báo hiệu luồng chính (nơi GUI) với giá trị cập nhật. Khi "Stop Counter" được nhấn, một tín hiệu sẽ được gửi đến luồng chính dừng vòng lặp while và bộ đếm sẽ dừng lại cho đến khi "Start Counter" được nhấn lần nữa.

Công trình này hoàn toàn tốt đẹp ... nhưng đó có phải là cách tốt nhất không? Tôi mới ở đây, và đọc rất nhiều người nói rằng "không phân lớp QThread" và những người khác nói "subclass QThread", và nó có một chút khó hiểu. Nếu đây không phải là cách tốt nhất để thực hiện loại điều này (chạy vòng lặp tính toán chuyên sâu trong chuỗi nền có nút "bắt đầu" và "dừng"), thì sao? Nếu tôi làm sai, làm thế nào để làm điều đó đúng? Tôi không muốn học sai cách.

Cảm ơn bạn! Và đây là đoạn code:

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

Hãy cẩn thận 'ngủ (1/1000) 'có nghĩa là' giấc ngủ (0)'. – deepmax

+0

@M M. Tốt bắt – Throwback1986

+0

Tốt, cảm ơn! Thay đổi nó thành giấc ngủ (0,001). – evdc

Trả lời

4

Hầu hết thời gian QThread sub-classing là một cách sai lầm để làm luồng trong Qt. Tôi khuyên bạn nên đọc một số article about threads, event loops and other để có thể cho bạn biết cách sử dụng chuỗi trong Qt theo cách tốt hơn. Nhưng đừng nghe bất cứ ai tranh cãi rằng có cách duy nhất để sử dụng QThread. Có 2 cách và trong khi phân lớp là không cần thiết nói chung nó đôi khi có thể hữu ích. Bạn chỉ cần sử dụng cách không phân lớp cho đến khi bạn thực sự cần phải phân lớp. Trong trường hợp cụ thể của bạn, bạn không cần subclassing.

+1

Vì vậy, những gì chính xác là _disadvantage_ sử dụng subclassing? (tức là, tại sao tôi nên _not_ sử dụng nó?) Có vẻ như với tôi rằng nó dễ dàng hơn nhiều so với việc tạo ra một QThread riêng biệt và một chuỗi công nhân riêng biệt và sau đó thực hiện moveToThread(). Ít nhất, khi sử dụng subclassing nó là dễ dàng hơn nhiều để hiểu những gì đang xảy ra. –

+0

@GijsvanOort, bài viết tôi đã đề cập ở trên trả lời câu hỏi của bạn. – ixSci

1

Thay sleep(1/1000); với msleep(100); Mọi thứ sẽ tốt :)

Các vấn đề liên quan