天天看點

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();//開啟事件循環
    }
}
           
這裡是引用:本文是個人開發學習記錄,如有差錯歡迎大神指點