Jestem nowy w StackOverflow i zastanawiam się, czy robię to dobrze:Proste wielowątkowość z Qt: czy robię to dobrze?
Piszę prostą aplikację Qt, aby przetestować wielowątkowość (coś, do czego jestem również całkowicie nowy). Zrobiłem MainWindow, który zawiera widżety i klasę MyThread, która podklasuje QThread i nadpisuje metodę run().
Aplikacja po prostu wyświetla dwa przyciski "Start Counter" i "Stop Counter" oraz pole tekstowe. Po naciśnięciu "licznika startu" tworzony jest wątek roboczy, który działa w tle, stale zwiększając licznik w pętli while i sygnalizując główny wątek (gdzie GUI jest) z zaktualizowaną wartością. Po naciśnięciu przycisku "Stop Counter" sygnał jest wysyłany do głównego wątku, który zatrzymuje pętlę while, a licznik jest zatrzymywany do momentu ponownego naciśnięcia przycisku "Start Counter".
Działa to idealnie dobrze ... ale czy to najlepszy sposób? Jestem w tym nowy i czytam wielu ludzi mówiących "nie podklas QThread" i innych ludzi mówiących "podklasę QThread", i to jest nieco mylące. Jeśli nie jest to najlepszy sposób na implementację tego rodzaju rzeczy (uruchom wymagającą obliczeniowo pętlę w wątku tła za pomocą przycisków "start" i "stop"), co to jest? Jeśli robię to źle, jak mam to zrobić dobrze? Nie chcę się uczyć w niewłaściwy sposób.
Dziękujemy! A oto kod:
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);
}
Uważać 'sleep (1/1000)' 'oznacza sen (0)'. – deepmax
@M M. Dobry połów – Throwback1986
Dobry połów, dzięki! Zmieniono go na sen (0,001). – evdc