天天看点

Qt多线程开发(QThread)

关于QT多线程开发介绍

  • QT下线程的创建方式

    Qt中主要有两种创建多线程的方式,一种是直接继承QThread重写run()函数来实现,另外一种是将一个继承于QObject的普通类通过moveToThread()方法移动到一个线程里去。 本文主要是理清如何正确的创建一个线程,和如何正确的退出一个线程。

本文主要记录QThread的普通用法,网上有许多相关资料,如果已经了解可忽视,本文重点介绍线程安全退出的方法。
  • 继承QThread重写run()函数线程创建方式
//.h文件
class Mythread:public QThread
{
    Q_OBJECT
public:
     Mythread(){}
    ~ Mythread(){}
    virtual void run();
   /*******************/
};
/****************************/
//.cpp文件
void Mythread::run()
{
    while (1)
    {
		//耗时操作	
    }
}
           
  • 继承于QObject的普通类通过moveToThread()方法移动到一个线程的创建方式
//.h文件
class Mythread:public QThread
{
    Q_OBJECT
public:
     Mythread(){}
    ~ Mythread(){}
    virtual void run();
   /*******************/
};
class MoveThread:public QObject
{
    Q_OBJECT
public:
    MoveThread(){}
    ~MoveThread(){}
};
class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
private:
    Ui::MainWindow *ui;
    Mythread * m_thread;
    MoveThread * m_movethread;
};
           
//.cpp文件
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
   ui->setupUi(this);
   m_thread= new Mythread ();
   m_movethread= new MoveThread ();
   m_movethread->moveToThread(m_thread);
}
           
二者创建线程的优缺点和差异在以后文章中会单独列出(关于Qt多线程下信号槽的调用机制及事件循环机制的介绍)
  • QT线程开启和退出

    线程开启函数:start()

不应该直接调用run函数,而应该使用**start()**函数

线程退出函数:quit()、exit()、terminate()用于线程终结退出

1.quit()函数告诉线程退出事件循环,让exec()返回0(成功)。等同于调用QThread::exit(0)。如果线程没有事件循环,这个函数什么事也不做。

2.exit()函数通知线程退出事件循环,并且传入一个code值。

调用该函数后,线程退出事件循环,并从QEventLoop::exec()调用中返回。QEventLoop::exec()返回一个returnCode码。一般情况,返回码为0意味着调用成功,非0值代表失败。

注意:和c库同名的函数不一样,调用该函数不返回一个值,它仅仅产生一个停止事件。

3.terminate()函数立即终止一个线程可以使用,但这个函数存在非常不安定因素,不推荐使用
4.线程调用wait()函数可以阻断本身的运行,直到其他的线程完成执行(或者一个指定的时间间隔后)。
  • 如何安全退出Qt线程
方法是添加一个bool变量,通过主线程修改这个bool变量来进行终止,但这样有可能引起访问冲突,所以需要加锁联合使用。具体操作如下:
//.h文件
class Mythread:public QThread
{
    Q_OBJECT
public:
    Mythread();
    ~Mythread();
    virtual void run();
    void runstart()
    {
        isCanRun=true;
    }
    void runstop()
    {
        isCanRun=false;
    }
    bool getcurrentstate()
    {
        return isCanRun;
    }
    /**********变量区**********/
protected:
    volatile bool isCanRun = false;
public slots:
    void stopImmediatelyS1();
private:
    static QMutex m_lock; //原子操作锁
    /*******************/
};
           
//.cpp文件
Mythread::Mythread()
{
    isCanRun = false;
    connect(this,SIGNAL(finished()),this,SLOT(deleteLater()));
}
QMutex Mythread::m_lock; //初始化静态锁
Mythread::~Mythread()
{
}
void Mythread::stopImmediatelyS1()
{
    QMutexLocker locker(&m_lock);
    isCanRun = false;
}
void Mythread::run()
{
    isCanRun = true;
    while (isCanRun)
    {
       //耗时操作
      {
       QMutexLocker locker(&m_lock);
       if(!isCanRun) //设置退出线程
       {
        return;
       }
      }
      exec();//开启事件循环
    }
}
           
这里是引用:本文是个人开发学习记录,如有差错欢迎大神指点