【例】(难度一般) 如图所示,单击“开始”按钮将启动数个工作线程(工作线程数目由MAXSIZE宏决定),各个线程循环打印数字0~9,直到按下“停止”按钮终止所有线程为止.
具体步骤如下。
(1)在头文件“threaddlg.h”中声明用于界面显示所需的控件,其具体代码如下:
#include <QDialog>
#include <QPushButton>
class ThreadDlg : public QDialog
{
Q_OBJECT
public:
ThreadDlg(QWidget *parent = 0);
~ThreadDlg();
private:
QPushButton *startBtn;
QPushButton *stopBtn;
QPushButton *quitBtn;
};
(2)在源文件“threaddlg.cpp”的构造函数中,完成各个控件的初始化工作,其具体代码如下:
#include "threaddlg.h"
#include <QHBoxLayout>
ThreadDlg::ThreadDlg(QWidget *parent)
: QDialog(parent)
{
setWindowTitle(tr("线程"));
startBtn = new QPushButton(tr("开始"));
stopBtn = new QPushButton(tr("停止"));
quitBtn = new QPushButton(tr("退出"));
QHBoxLayout *mainLayout = new QHBoxLayout(this);
mainLayout->addWidget(startBtn);
mainLayout->addWidget(stopBtn);
mainLayout->addWidget(quitBtn);
}
(3)此时运行程序,界面显示上图所示。
以上完成了界面的设计,下面的内容是具体的功能实现。
(1)在头文件“workthread.h”中,工作线程WorkThread类继承自QThread类。重新实现run()函数。其具体代码如下:
#include <QThread>
class WorkThread : public QThread
{
Q_OBJECT
public:
WorkThread();
protected:
void run();
};
(2)在源文件“workthread.cpp”中添加具体实现代码如下:
#include "workthread.h"
#include <QtDebug>
WorkThread::WorkThread()
{
}
run()函数实际上是一个死循环,它不停地打印数字0~9。为了显示效果明显,程序将每一个数字重复打印8次。
void WorkThread::run()
{
while(true)
{
for(int n=0;n<10;n++)
qDebug()<<n<<n<<n<<n<<n<<n<<n<<n;
}
}
(3)在头文件“threaddlg.h”中添加以下内容:
#include "workthread.h"
#define MAXSIZE 1 //MAXSIZE宏定义了线程的数目
public slots:
void slotStart(); //槽函数用于启动线程
void slotStop(); //槽函数用于终止线程
private:
WorkThread *workThread[MAXSIZE]; //(a)
(4)在源文件“threaddlg.cpp”中添加以下内容。
其中,在构造函数中添加如下代码:
connect(startBtn,SIGNAL(clicked()),this,SLOT(slotStart()));
connect(stopBtn,SIGNAL(clicked()),this,SLOT(slotStop()));
connect(quitBtn,SIGNAL(clicked()),this,SLOT(close()));
槽函数slotStart(),当用户单击“开始”按钮时,此函数将被调用。这里使用两个循环,目的是为了使新建的线程尽可能同时开始执行,其具体实现代码如下:
void ThreadDlg::slotStart()
{
for(int i=0;i<MAXSIZE;i++)
{
workThread[i]=new WorkThread(); //(a)
}
for(int i=0;i<MAXSIZE;i++)
{
workThread[i]->start(); //(b)
}
startBtn->setEnabled(false);
stopBtn->setEnabled(true);
}
槽函数slotStop(),当用户单击“停止”按钮时,此函数将被调用。其具体实现代码如下:
void ThreadDlg::slotStop()
{
for(int i=0;i<MAXSIZE;i++)
{
workThread[i]->terminate();
workThread[i]->wait();
}
startBtn->setEnabled(true);
stopBtn->setEnabled(false);
}
(5)运行结果如下图所示。
第1列是启动五个线程的运行结果,第2列是启动单一线程的运行结果。可以看出,单一线程的输出是顺序打印的,而多线程的输出结果则是乱序打印的,这正是多线程的一大特点。