So I have a simple Qt4 application with a Start button, a Stop button, and a text field. When the Start button is pressed, a new thread is spawned that continually increments a counter (in a while loop), and the text field is updated to reflect this via signals/slots. When the Stop button is pressed, the counting stops, until the Start button is pressed again.
It works ... sort of. It only updates the counter once per second; I want it to go faster, say 44100 times per second. Taking out the sleep(1) call, however, causes the while loop to block, no GUI events are recognized, and the application freezes. Also, the Stop button only works on the second try?
This used to work pretty much fine when I was subclassing QThread, but I was told not to do that, so I tried making a solution with subclassing QObject and then moving the object to a QThread ... but it isn't working as well as it used to.
Here's the code:
Worker.h
class Worker : public QObject
{
Q_OBJECT
public:
Worker();
public slots:
void process();
void stopRunning();
signals:
void signalValueUpdated(QString);
private:
bool running;
};
Worker.cpp
#include "Worker.h"
void Worker::process()
{
qDebug("Worker thread id %d",(int)QThread::currentThreadId());
static int value=0;
running = 1;
while(running == 1)
{
QString string = QString("value: %1").arg(value++);
sleep(1); //I want to take this out or make it way shorter but I can't without it crashing.
emit signalValueUpdated(string);
QCoreApplication::processEvents();
}
}
void Worker::stopRunning()
{
qDebug("stopRunning() invoked");
running = 0;
}
MainWindow.h
class MainWindow : public QWidget
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
private:
//Widgets
QHBoxLayout * boxLayout;
QPushButton * startButton;
QPushButton * stopButton;
QLineEdit * lineEdit;
//Thread where the worker lives
QThread * workerThread;
//Worker object itself
Worker * worker;
};
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());
workerThread = new QThread;
worker = new Worker();
worker->moveToThread(workerThread);
connect( startButton, SIGNAL(clicked()), workerThread, SLOT(start()), Qt::QueuedConnection ); //When the start button is clicked, start the worker thread
connect( startButton, SIGNAL(clicked()), worker, SLOT(process()), Qt::QueuedConnection ); //When the start button is clicked, start the worker thread
connect( workerThread, SIGNAL(started()), worker, SLOT(process()), Qt::QueuedConnection ); //When the worker thread starts, begin the Worker object's process function
connect( stopButton, SIGNAL(clicked()), worker, SLOT(stopRunning()), Qt::QueuedConnection ); //When the stop button is clicked, invoke the Worker's stopRunning()
connect( worker, SIGNAL(signalValueUpdated(const QString&)), lineEdit, SLOT(setText(const QString&)), Qt::QueuedConnection ); //When the Worker emits a signalValueChanged, update the lineEdit to reflect this
}
Without sleep(1) and processEvents() in Worker.cpp, the whole thing crashes, but with them it is slowed down too much, only updating the number once per second instead of 1000 or more. How can I make the while(running) loop not block?
Thanks in advance! Still trying to wrap my head around the best way to do multithreading in Qt.