Qt4_创建线程

创建线程

在Qt应用程序中提供多钱程是非常简单的:只需要子类化QThread 并且重新实现它的 run()函数就可以了。为了显示这一过程是如何进行的,我们将从介绍一个非常简单的QThread子类的代码开始,它是一个可以在控制台上重复打印给定字符串的子类。应用程序的用户接口界面如:

Thread.h

#ifndef THREAD_H
#define THREAD_H

#include <QThread>

class Thread : public QThread
{
    Q_OBJECT

public:
    Thread();

    void setMessage(const QString &message);
    void stop();

protected:
    void run();

private:
    QString messageStr;
    volatile bool stopped;
};

#endif

这里的Thread 类派生自QThread 类,并且重新实现了 run() 函数。这个类还额外提供了两个函数:因setMessage()和 stop()。

stopped 被声明为易失性变量(volatile variable,断电或中断时数据丢失而不可再恢复的变量型) ,这是因为不同的线程都需要访问它,并且我们也希望确保它能够在任何需要的时候都保最新读取的数值。如果省略 volatile 关键字,则编译器就会对这个变量的访问进行优化,那么就能导致不正确的结果。

Thread.cpp

#include <QtCore>
#include <iostream>

#include "thread.h"

Thread::Thread():stopped(false){} //构造函数

void Thread::setMessage(const QString &message)
{
    messageStr = message;
}

void Thread::run()
{
    while (!stopped)
        std::cerr << qPrintable(messageStr);
    stopped = false;
    std::cerr << std::endl;
}

void Thread::stop()
{
    stopped = true;
}

Thread()
在构造图数中把 stopped 设置为 false。

run()
在开始执行线程的时,就会调用 run() 函数。只要 stopped 变量为 false 值,这个函数就会一向控制台打印输出给定的消息。当控制离开 run() 函数时,就会终止线程。

stop()
stop()函数会把 stopped 变量设置为 true ,从而告诉run()停止向控制台输出文本。任何时候stop()函数都可以由任一线程调用。考虑到这个实例的目的,我们假定对bool变量的赋值是一个原子操作。这是一个合理的假设,因为bool变量仅能有两种状态。在这一节的稍后部分,到如何使用 QMutex 确保对一个变量的赋值成为一个原子操作。

QThread提供了一个terminate()函数,该函数可以在一个线程还在运行的时候就终止它的执行。我们不推荐使用terminate(),这是因为它可以随时停止线程执行而不给这个线程自我清空的机会。一种更为安全的方法是使用stopped变量和stop()函数,就像这里所做的那样。

ThreadDialog.h

下面将给出如何在一个简单的Qt应用程序中使用Thread类的示例,这个应用程序除了主线程之外还使用了两个线程,即线程 A和线程 B。

#ifndef THREADDIALOG_H
#define THREADDIALOG_H

#include <QDialog>

#include "thread.h"

class QPushButton;

class ThreadDialog : public QDialog
{
    Q_OBJECT

public:
    ThreadDialog(QWidget *parent = 0);

protected:
    void closeEvent(QCloseEvent *event);

private slots:
    void startOrStopThreadA();
    void startOrStopThreadB();

private:
    Thread threadA;
    Thread threadB;
    QPushButton *threadAButton;
    QPushButton *threadBButton;
    QPushButton *quitButton;
};

#endif

ThreadDialog 类声明了两个类型为Thread 的变量和一些按钮,提供基本的用户界面。

ThreadDialog.cpp

#include <QtGui>

#include "threaddialog.h"

ThreadDialog::ThreadDialog(QWidget *parent)
    : QDialog(parent)
{
    threadA.setMessage("A");
    threadB.setMessage("B");

    threadAButton = new QPushButton(tr("Start A"));
    threadBButton = new QPushButton(tr("Start B"));
    quitButton = new QPushButton(tr("Quit"));
    quitButton->setDefault(true);

    connect(threadAButton, SIGNAL(clicked()),
            this, SLOT(startOrStopThreadA()));
    connect(threadBButton, SIGNAL(clicked()),
            this, SLOT(startOrStopThreadB()));
    connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));

    QHBoxLayout *mainLayout = new QHBoxLayout;
    mainLayout->addWidget(threadAButton);
    mainLayout->addWidget(threadBButton);
    mainLayout->addWidget(quitButton);
    setLayout(mainLayout);

    setWindowTitle(tr("Threads"));
}

void ThreadDialog::startOrStopThreadA()
{
    if (threadA.isRunning()) {
        threadA.stop();
        threadAButton->setText(tr("Start A"));
    } else {
        threadA.start();
        threadAButton->setText(tr("Stop A"));
    }
}

void ThreadDialog::startOrStopThreadB()
{
    if (threadB.isRunning()) {
        threadB.stop();
        threadBButton->setText(tr("Start B"));
    } else {
        threadB.start();
        threadBButton->setText(tr("Stop B"));
    }
}

void ThreadDialog::closeEvent(QCloseEvent *event)
{
    threadA.stop();
    threadB.stop();
    threadA.wait();
    threadB.wait();
    event->accept();
}

ThreadDialog()
在构造函数中,调用 setMessage()让第一个线程重复打印字母"A" ,而让第二个线程重复打印宇母"B" 。

startOrStopThreadA()
当用户单击用于线程的按钮时,如果这个线程正在运行, startOrStopThreadA()就让它停止运行;否则,就让它开始运行。startOrStopThreadA()同时还更新该按钮上的文本。

startOrStopThreadB()
startOrStopThreadB()的代码与startOrStopThreadA()的代码在结构上基本一致。

closeEvent()
如果用户单击了Quit或者关闭了窗口,就停止所有正在运行的线程,并且在调用函数QCloseEvent::accept()之前等待它们完全结束[可使用QThread::wait()]。这样就可以确保应用程序是以一种原始清空的状态而退出的,尽管在这个实例中是否这样做并不要紧。

如果运行这个应用程序,并且单击按钮"Start A",那么控制台终端就会被连续输出的字母"A"填满。如果再单击按钮"Start B",那么控制台终端就会被以交替顺序输出的字母"A"和"B"填满。如果再单击按钮"Stop A",那么就将只输出字母"B"。

main.cpp

#include <QApplication>

#include "threaddialog.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    ThreadDialog dialog;
    dialog.show();
    return app.exec();
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阳光开朗男孩

你的鼓励是我最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值