所以我有一个简单的Qt4应用程序,它带有一个开始按钮,一个停止按钮和一个文本字段。按下“开始”按钮时,会生成一个新线程,该线程会不断递增计数器(在while循环中),并更新文本字段以通过信号/插槽反映这一点。按下“停止”按钮后,计数停止,直到再次按下“开始”按钮。
它有效......有点儿。它每秒只更新一次计数器;我希望它更快,比如每秒44100次。但是,取出sleep(1)调用会导致while循环被阻塞,没有识别出GUI事件,并且应用程序冻结。此外,停止按钮仅适用于第二次尝试?
当我继承QThread时,这曾经工作得非常好,但我被告知不要这样做,所以我尝试用子类化QObject然后将对象移动到QThread来制作解决方案......但它不是和以前一样工作。
以下是代码:
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
}
在Worker.cpp中没有sleep(1)和processEvents(),整个事情崩溃了,但是它们会慢下来,只是每秒更新一次而不是1000或更多。如何使while(running)循环不阻塞?
提前致谢!仍然试图围绕在Qt中进行多线程处理的最佳方式。
答案 0 :(得分:2)
如果您不需要,请删除worker中的QCoreApplication::processEvents()
(为什么需要它?GUI事件应该已经由主线程处理...)。这可能是您的问题的原因。
以正确的方式连接线程信号:
connect(workerThread, SIGNAL(started()), worker, SLOT(process()));
connect(startButton, SIGNAL(clicked()), thread, SLOT(start()));
(删除startButton.clicked()
- > worker.process()
的连接 - 它没用,并且没有按照评论中的内容执行操作)
因为将按钮直接连接到worker中的进程是不对的。您应该将按钮连接到Thread的开头,然后将Thread(已启动)连接到worker process()
。避免直接连接应该避免您遇到的GUI冻结问题。
此外,您需要创建一个新线程并在每次单击按钮时“触发”它。您可以通过将按钮连接到窗口中的SLOT
并从中创建线程(在MainWindow
构造函数中创建它不起作用)来完成。
取自(工作)计划,我有:
// You need another slot in MainWindow, let it be "startProcessing()"
// in MainWindow::MainWindow, connect the start button to startProcessing()
connect(btnStart, signal(clicked(), this, SLOT(startProcessing())
// inside the startProcessing slot
void MainWindow::startProcessing() {
...
Worker* worker = new Worker;
QThread* thread = new QThread;
// start the work
worker->moveToThread(thread);
connect(thread, SIGNAL(started()), worker, SLOT(process()));
// Take care of cleaning up when finished too
connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
}
您可能已经注意到,我也添加了代码来清理它(deleteLater()
)。
停止按钮也会给你一些问题,但你现在应该知道如何继续。