Qt中的线程应用 [英] Thread application in Qt
问题描述
我正在学习在 Qt 中使用线程进行管理,所以如果我犯了一些小错误,请向我道歉.让我们回到正题.
简短说明:
我编写了一个小应用程序来测试线程的工作方式.我有两个按钮的简单 GUI 界面.他们每个人都可以启动和停止不同的线程.线程基于
Creating new object inside button method 而不是 MyDialog
ctor 解决了我的问题.例如:
void MainWindow::startStopThreadA(){//第一种方法 - 启动/停止线程if(threadA && threadA->isRunning()){workerA->stop();线程A = nullptr;ui->threadAButton->setText("Start A");}别的{threadA = 新的 QThread;workerA = 新的 WorkerObject;workerA->setMessage("线程 A 正在运行");workerA->moveToThread(threadA);连接(线程A,信号(开始()),工人A,插槽(进程()),Qt::QueuedConnection);连接(工人A,信号(完成()),线程A,插槽(退出()));连接(工人A,信号(完成()),工人A,插槽(deleteLater()));连接(线程A,信号(完成()),线程A,插槽(deleteLater()));线程A->开始();ui->threadAButton->setText("Stop A");}}
I'm learning managing with threads in Qt, so please apologize me if I'm making trivial mistakes. Let's back to the topic.
Short description:
I wrote small application for testing how threads work. I have simple GUI interface with two buttons. Each of them can starts and stops different thread. Threads are based on Worker class under this link. I'm compiling my code with Qt Creator under Ubuntu 16.04 LTS x64.
Main questions:
- When I try start thread it works proper. Then I stop it and try to start again. In this case thread doesn't start. Maby I'm closing thread by inproper way?
- Is this way of managing with threads is proper? Is it done well? I read about that moving QObject to threads is better in Qt than subclass threads. (But it depends, I know).
My code:
worker.h:
#ifndef WORKER_H
#define WORKER_H
#include <QObject>
#include <QMutex>
class Worker : public QObject
{
Q_OBJECT
public:
explicit Worker(QObject *parent = nullptr);
void stop();
void setMessage(const QString &message);
signals:
void finished();
public slots:
void process();
private:
volatile bool stopped;
QString messageStr;
QMutex mutex;
};
#endif // WORKER_H
worker.cpp:
#include "worker.h"
#include <QDebug>
Worker::Worker(QObject *parent)
: QObject(parent)
{
stopped = false;
}
void Worker::process()
{
forever
{
mutex.lock();
if(stopped)
{
stopped = false;
mutex.unlock();
break;
}
mutex.unlock();
qDebug() << messageStr;
}
emit finished();
}
void Worker::stop()
{
mutex.lock();
stopped = true;
mutex.unlock();
}
void Worker::setMessage(const QString &message)
{
messageStr = message;
}
mydialog.h:
#ifndef MYDIALOG_H
#define MYDIALOG_H
#include <QDialog>
class Worker;
class MyDialog : public QDialog
{
Q_OBJECT
public:
MyDialog(QWidget *parent = nullptr);
private slots:
void startStopThreadA();
void startStopThreadB();
void showWorkingGUI();
private:
Worker *workerA;
Worker *workerB;
QThread *threadA;
QThread *threadB;
QPushButton *threadAButton;
QPushButton *threadBButton;
QPushButton *quitButton;
};
#endif // MYDIALOG_H
mydilog.cpp:
#include "mydialog.h"
#include "worker.h"
#include <QCloseEvent>
#include <QHBoxLayout>
#include <QPushButton>
#include <QThread>
#include <QDebug>
#include <QTimer>
MyDialog::MyDialog(QWidget *parent)
: QDialog(parent)
{
//Here bla bla for gui
threadAButton = new QPushButton(tr("Start A"));
threadBButton = new QPushButton(tr("Start B"));
quitButton = new QPushButton(tr("Quit"));
connect(threadAButton, SIGNAL(clicked()), this, SLOT(startStopThreadA()));
connect(threadBButton, SIGNAL(clicked()), this, SLOT(startStopThreadB()));
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(threadAButton);
layout->addWidget(threadBButton);
layout->addWidget(quitButton);
setLayout(layout);
//Create worker's instances
workerA = new Worker;
workerB = new Worker;
workerA->setMessage("Thread 1");
workerB->setMessage("Thread 2");
//Create threads instances
threadA = new QThread;
threadB = new QThread;
//Move worker to thread
workerA->moveToThread(threadA);
workerB->moveToThread(threadB);
connect(threadA, SIGNAL(started()), workerA, SLOT(process()));
connect(workerA, SIGNAL(finished()), threadA, SLOT(quit()));
connect(workerA, SIGNAL(finished()), workerA, SLOT(deleteLater()));
connect(threadA, SIGNAL(finished()), threadA, SLOT(deleteLater()));
connect(threadB, SIGNAL(started()), workerB, SLOT(process()));
connect(workerB, SIGNAL(finished()), threadB, SLOT(quit()));
connect(workerB, SIGNAL(finished()), workerB, SLOT(deleteLater()));
connect(threadB, SIGNAL(finished()), threadB, SLOT(deleteLater()));
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(showWorkingGUI()));
timer->start(1000);
}
void MyDialog::startStopThreadA()
{
if(threadA->isRunning())
{
workerA->stop();
threadAButton->setText(tr("Start A"));
}
else
{
threadA->start();
threadAButton->setText(tr("Stop A"));
}
}
void MyDialog::startStopThreadB()
{
if(threadB->isRunning())
{
workerB->stop();
threadBButton->setText(tr("Start B"));
}
else
{
threadB->start();
threadBButton->setText(tr("Stop B"));
}
}
void MyDialog::showWorkingGUI()
{
qDebug() << "GUI Thread works!";
}
And main.cpp:
#include <QApplication>
#include "mydialog.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MyDialog dialog;
dialog.show();
return a.exec();
}
Please for some help. Don't laugh at me if I made some mistakes. I'm really new in threads :)
EDIT: I forgot to attach image:
Creating new object inside button method instead MyDialog
ctor solved my problem. For example:
void MainWindow::startStopThreadA()
{
//First method - start/stop thread
if(threadA && threadA->isRunning())
{
workerA->stop();
threadA = nullptr;
ui->threadAButton->setText("Start A");
}
else
{
threadA = new QThread;
workerA = new WorkerObject;
workerA->setMessage("Thread A running");
workerA->moveToThread(threadA);
connect(threadA, SIGNAL(started()), workerA, SLOT(process()), Qt::QueuedConnection);
connect(workerA, SIGNAL(finished()), threadA, SLOT(quit()));
connect(workerA, SIGNAL(finished()), workerA, SLOT(deleteLater()));
connect(threadA, SIGNAL(finished()), threadA, SLOT(deleteLater()));
threadA->start();
ui->threadAButton->setText("Stop A");
}
}
这篇关于Qt中的线程应用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!