实现线程的两种方法:
(1) 派生QThread并重写run()函数;
(2) 使用 QObject::moveToThread(QThread); (推荐 )
1. 常用接口
槽函数:
作用: 开启线程,通过调用run函数开始线程执行;操作系统根据优先级参数调度线程;若该线程已经运行了,
则该函数什么也不做;
void QThread::start(QThread::Priority priority = InheritPriority);
enum Priority {
IdlePriority,//只有在没有其他线程运行时才调度。
LowestPriority,//调度频率低于LowPriority。
LowPriority, //调度频率低于NormalPriority。
NormalPriority,//操作系统的默认优先级。
HighPriority, //调度比NormalPriority更频繁。
HighestPriority,//调度比HighPriority更频繁
TimeCriticalPriority,//尽可能的被调度
InheritPriority //使用与创建线程相同的优先级。这是默认值。
};
作用:终止线程的执行;该线程可能立即终止,也可能不会;取决于操作系统调度策略;
所以terminate后应该使用 wait函数;
void QThread::terminate();
作用:告诉线程事件循环退出,返回0; 等同于exit(0); 若没有事件循环,则什么都不做;
void QThread::quit();
信号:
该信号从关联的线程 在run()函数运行前发出;
void started();
该信号从关联的线程 在完成执行前发出;当信号被发出时,事件循环已经停止运行了;
void finished();
线程被中断时候发出
void terminated();//qt5可能取消;
公共函数:
设置调度优先级
void setPriority(Priority priority);
获取调度优先级
Priority priority() const;
设置栈大小,stackSize>0设置才有效;注意:线程运行时不可以改变栈大小;
void QThread::setStackSize(uint stackSize);
获取栈大小
uint QThread::stackSize() const
如果线程结束,返回true;否则返回false。
bool isFinished() const;
如果线程正在运行,返回true;否则返回false。
bool isRunning() const;
静态成员:
线程延时函数:强制该线程延时一段时间;
static void sleep(unsigned long);
static void msleep(unsigned long);
static void usleep(unsigned long);
//获取该线程句柄,为void *;
static Qt::HANDLE currentThreadId();
//返回管理该线程对象的指针
static QThread *currentThread();
保护成员函数:
进入事件循环并且等待,直到exit(0)被调用;
这个函数应该在run()中调用。需要调用此函数来启动事件处理。
int QThread::exec();
线程的起始点。在调用start()之后,新创建的线程调用这个函数。默认实现只调用exec()。
void QThread::run();
2. 派生QThread并重写run()函数
(a) 子类化QThread,重写run,run中使用while循环,设置退出标志;
class MyThread : public QThread
{
Q_OBJECT
public:
MyThread(){isRuning = true;}
//改变线程运行状态
void ChangeThreadRunStatus(bool status)
{
isRuning = status;
}
protected:
void run()
{
while(isRuning)
{
qDebug() << "thread is running..." << endl;
sleep(1);
}
}
private:
bool isRuning ;
};
//测试头文件
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
protected:
void closeEvent(QCloseEvent *e);
private:
Ui::Widget *ui;
MyThread *mythread;
};
//测试cpp
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
mythread = new MyThread();
connect(mythread, SIGNAL(finished()), mythread, SLOT(deleteLater()));
mythread->start();
}
Widget::~Widget()
{
//从Qt4.8开始,通过将finished()信号连接到QObject::deleteLater(),可以释放刚刚结束的线程中的对象。尽可能的使用deleteLater方法释放内存;
#if 0
mythread->exit(0);
//等待线程完全退出后在析构
//不等待会出现 QThread: Destroyed while thread is still running
//线程的run中有一个sleep,不等待可能run没退出就delete掉该线程;
mythread->wait();
delete mythread;
#endif
delete ui;
}
void Widget::closeEvent(QCloseEvent *e)
{
qDebug() << "closeEvent" << endl;
mythread->ChangeThreadRunStatus(false);//关闭窗口时停止线程;
}
(b) 子类化QThread,重写run()函数,在run中调用exec事件循环;
在其中使用信号和槽, 由于槽函数并没有运行子线程中(参考);故用moveToThread方法;