Qt中的线程应用 [英] Thread application in Qt

查看:47
本文介绍了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:

  1. 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?
  2. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆