一、常用相关函数
可以将常用的函数按照功能进行以下分类:
-
线程启动
-
void start()
调用后会执行run()函数,但在run()函数执行前会发射信号started(),操作系统将根据优先级参数调度线程。如果线程已经在运行,那么这个函数什么也不做。优先级参数的效果取决于操作系统的调度策略。
-
-
线程执行
-
int exec()
每一个线程可以有自己的事件循环,可以通过调用exec()函数来启动事件循环。
-
void run()
线程的起点,在调用start()之后,新创建的线程就会调用这个函数,默认实现调用exec(),大多数需要重新实现这个函数,便于管理自己的线程。该函数返回后,线程便执行结束,就像应用程序离开main()函数一样。
-
-
线程退出
-
void quit()
使线程退出事件循环,返回0表示成功,相当于调用了QThread::exit(0)。
-
void exit(int returnCode = 0)
使线程退出事件循环,返回0表示成功,任何非0值表示失败。
-
void terminate()
在极端情况下,可能想要强制终止一个正在执行的线程,这时可以使用terminate()函数。但是,线程可能会立即被终止也可能不会,这取决于操作系统的调度策略,使用terminate()之后再使用QThread::wait(),以确保万无一失。
警告:使用terminate()函数,线程可能在任何时刻被终止而无法进行一些淸理工作,因此该函数是很危险的,一般不建议使用,只有在绝对必要的时候使用。
-
void requestInterruption()
Qt5新引入接口,请求线程的中断,用于关闭线程。该请求是咨询意见并且取决于线程上运行的代码,来决定是否及如何执行这样的请求。此函数不停止线程上运行的任何事件循环,并且在任何情况下都不会终止它。
-
-
线程等待
-
void msleep(unsigned long msecs) [static]
强制当前线程睡眠msecs毫秒。
-
void sleep(unsigned long secs) [static]
强制当前线程睡眠secs秒。
-
void usleep(unsigned long usecs) [static]
强制当前线程睡眠usecs微秒。
-
bool wait(unsigned long time = ULONG_MAX)
线程将会被阻塞,等待time毫秒。和sleep不同的是,如果线程退出,wait会返回。
-
-
线程状态
-
bool isFinished() const
判断线程是否结束
-
bool isRunning() const
判断线程是否正在运行
-
bool isInterruptionRequested() const
如果线程上的任务运行应该停止,返回true;可以使用requestInterruption()请求中断。 Qt5新引入接口,用于使长时间运行的任务干净地中断。从不检查或作用于该函数返回值是安全的,但是建议在长时间运行的函数中经常这样做。注意:不要过于频繁调用,以保持较低的开销。示例程序如下:void run() {// 是否请求终止while (!isInterruptionRequested()){// 耗时操作} }
-
-
线程优先级
-
void setPriority(Priority priority)
设置正在运行线程的优先级。如果线程没有运行,此函数不执行任何操作并立即返回。使用的start()来启动一个线程具有特定的优先级。优先级参数可以是QThread::Priority枚举除InheritPriortyd的任何值。
-
枚举QThread::Priority:
常量 | 值 | 描述 |
---|---|---|
QThread::IdlePriority | 0 | 没有其它线程运行时才调度 |
QThread::LowestPriority | 1 | 比LowPriority调度频率低 |
QThread::LowPriority | 2 | 比NormalPriority调度频率低 |
QThread::NormalPriority | 3 | 操作系统的默认优先级 |
QThread::HighPriority | 4 | 比NormalPriority调度频繁 |
QThread::HighestPriority | 5 | 比HighPriority调度频繁 |
QThread::TimeCriticalPriority | 6 | 尽可能频繁的调度 |
QThread::InheritPriority | 7 | 使用和创建线程同样的优先级. 这是默认值 |
二、QThread线程启动方式
一、继承QThread,实现它的run()函数,将需要执行的耗时代码放在run()里面运行
void myThread::run()
{m_stop = false;while (!m_stop){/*耗时任务*/...}
}
此方法,如果要退出可使用
void myThread::stop()
{m_stop = true;quit();wait();
}
使用时,调用start()函数,则相当于执行run()函数,在程任务执行完毕时,会发出 finished() 信号
/*子类化线程*/
mythread = new myThread();
connect(mythread,SIGNAL(finished()),this,SLOT(dealfinished()));
mythread->start();
二、使用moveToThread()。即子类化一个QObject实现需要执行的操作,再将派生类对象移到QThread中,并通过信号和槽触开始执行。
/*QObject派生类,即耗时工作在这里实现*/
work = new Work;
/*通过信号和槽获取返回信息*/
connect(work,SIGNAL(resultReady(int)),this,SLOT(dealWorkresultReady(int)));/*将派生类对象移动到QThread中*/
thread = new QThread(this);
connect(thread,SIGNAL(finished()),this,SLOT(dealfinished_2()));
work->moveToThread(thread);
/*通过信号链接派生类的槽函数,并通过信号触发*/
connect(thread,SIGNAL(started()),work,SLOT(start()));
thread->start();
三、实现案例及代码
方式一:子类化QThread
mythread.h
#ifndef MYTHREAD_H
#define MYTHREAD_H#include <QThread>class myThread : public QThread
{Q_OBJECT
public:explicit myThread(QObject *parent = NULL);void stop();
protected:virtual void run();signals:void resultReady(int value);
private:bool m_stop;
};#endif // MYTHREAD_H
mythread.cpp
#include "mythread.h"
myThread::myThread(QObject *parent) : QThread(parent)
{
}void myThread::stop()
{m_stop = true;quit();wait();
}void myThread::run()
{/*start会触发run,即需要执行的耗时工作加这里*/m_stop = false;int nValue = 0;while (nValue < 100 && !m_stop){emit resultReady(nValue);/*耗时0.5秒*/system("sleep 0.5");++nValue;/*发送信号,更新进度条*/}
}
方式二:子类化QObject
work.h
#ifndef WORK_H
#define WORK_H#include <QObject>class Work : public QObject
{Q_OBJECT
public:explicit Work(QObject *parent = NULL);void stop();public slots:void start();
signals:void resultReady(int value);
private:bool m_stop;
};#endif // WORK_H
work.cpp
#include "work.h"
Work::Work(QObject *parent) : QObject(parent)
{}void Work::stop()
{m_stop = true;
}void Work::start()
{m_stop = false;int nValue = 0;while (nValue < 100 && !m_stop ){emit resultReady(nValue);/*耗时0.5秒*/system("sleep 0.5");++nValue;}
}
效果图界面 widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QDateTime>
#include <QDebug>
Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);/*定时器,加载时间*/timer = new QTimer(this);connect(timer,SIGNAL(timeout()),this,SLOT(dealTimeout()));timer->start(1000);ui->progressBar->setValue(0);ui->progressBar->setMaximum(100);ui->progressBar_2->setValue(0);ui->progressBar_2->setMaximum(100);ui->progressBar_3->setValue(0);ui->progressBar_3->setMaximum(100);/*子类化线程*/mythread = new myThread(this);connect(mythread,SIGNAL(resultReady(int)),this,SLOT(dealresultReady(int)));connect(mythread,SIGNAL(finished()),this,SLOT(dealfinished()));/*QObject派生类,即耗时工作在这里实现*/work = new Work;/*通过信号和槽获取返回信息*/connect(work,SIGNAL(resultReady(int)),this,SLOT(dealWorkresultReady(int)));/*将派生类对象移动到QThread中*/thread = new QThread(this);connect(thread,SIGNAL(finished()),this,SLOT(dealfinished_2()));work->moveToThread(thread);/*通过信号链接派生类的槽函数,并通过信号触发*/connect(thread,SIGNAL(started()),work,SLOT(start()));}Widget::~Widget()
{delete ui;
}void Widget::dealresultReady(int value)
{ui->progressBar->setValue(value);
}void Widget::dealWorkresultReady(int value)
{ui->progressBar_3->setValue(value);
}void Widget::on_pushButton_1_clicked()
{if(!mythread->isRunning()){ui->pushButton_1->setText("stop");mythread->start();}else{ui->pushButton_1->setText("start_1");mythread->stop();}
}void Widget::on_pushButton_2_clicked()
{if(!thread->isRunning()){ui->pushButton_2->setText("stop");thread->start();}else{ui->pushButton_2->setText("start_2");work->stop();thread->quit();thread->wait();}
}void Widget::on_pushButton_clicked()
{ui->label_2->setText("<font style='color: red;'>完犊子,直接卡死! 点其他按钮么反应! 时间都没更新了!</font>");update();int cnt=0;while(cnt < 100){system("sleep 0.5");ui->progressBar_2->setValue(cnt);cnt++;update();}
}void Widget::dealfinished()
{qDebug()<< "start_1 over";
}void Widget::dealfinished_2()
{qDebug()<< "start_2 over";
}void Widget::dealTimeout()
{QDateTime dateTime = QDateTime::currentDateTime();QString date = dateTime.toString("hh:mm:ss");ui->label_3->setText("当前时间:"+date);
}
原文链接:https://blog.csdn.net/kchmmd/article/details/121202881