我正在学习Qt中的线程管理,所以如果我犯了琐碎的错误,请向我道歉。让我们回到主题。
简短说明:
我编写了一个小应用程序来测试线程的工作方式。我有简单的GUI界面和两个按钮。他们每个人都可以启动和停止不同的线程。主题基于this link下的工作人员类。我正在使用 Ubuntu 16.04 LTS x64 下的 Qt Creator 编译我的代码。
主要问题:
我的代码:
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!";
}
和main.cpp:
#include <QApplication>
#include "mydialog.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MyDialog dialog;
dialog.show();
return a.exec();
}
请寻求帮助。如果我犯了一些错误,不要嘲笑我。我是线程中的新手:)
答案 0 :(得分:0)
在按钮方法中创建新对象而不是MyDialog
ctor解决了我的问题。例如:
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");
}
}