Qt 線程幾種使用方法代碼實例

Qt 線程的詳細介紹和使用


  • QT::QThread類提供了一種獨立於平臺的方式來管理線程。QThread對象管理程序中的一個控制線程。QThreads開始在run()中執行。默認情況下,run()通過調用exec()啓動事件循環,並在線程內部運行Qt事件循環

  • 通過使用QObject::moveToThread()將worker對象移動到線程,可以使用它。線程將在運行函數返回後退出。除非調用exec(),否則線程中不會運行任何事件循環。

 

  • 必須記住,QThread實例位於實例化它的舊線程中,而不是調用run()的新線程中。
  • 這意味着QThread隊列中的所有插槽都將在舊線程中執行。
  • 因此,希望在新線程中調用插槽的開發人員必須使用worker-object方法;不應該將新插槽直接實現到子類QThread中。
  • 在子類化QThread時,請記住,構造函數在舊線程中執行,而run()在新線程中執行。
  • 如果從兩個函數訪問成員變量,則從兩個不同的線程訪問該變量。檢查一下這樣做是否安全。
  • 當線程啓動()和finished()時,QThread將通過一個信號通知您,或者您可以使用isFinished()和isRunning()來查詢線程的狀態。
  • 您可以通過調用exit()或quit()來停止線程。在極端情況下,您可能希望強制終止一個正在執行的線程。然而,這樣做是危險的,也是令人氣餒的。詳細信息請閱讀terminate()和setTerminationEnabled()的文檔。
  • 從Qt 4.8開始,通過將finished()信號連接到QObject::deleteLater,就可以釋放位於剛剛結束的線程中的對象
  • 使用wait()來阻塞調用的線程,直到另一個線程完成執行(或者直到指定的時間過去)。
  • QThread還提供靜態的、平臺無關的睡眠函數:sleep()、msleep()和usleep()分別允許完全秒級、毫秒級和微秒級的分辨率。這些功能在Qt 5.0中公開。
  • 注意:一般來說,wait()和sleep()函數應該是不必要的,因爲Qt是一個事件驅動框架。考慮偵聽完成的()信號,而不是wait()。不要使用sleep()函數,考慮使用QTimer。
  • 靜態函數currentThreadId()和currentThread()返回當前執行線程的標識符。前者返回線程的平臺特定ID;後者返回一個QThread指針。
  • 要選擇線程的名稱(例如,通過Linux上的命令ps -L識別),可以在啓動線程之前調用setObjectName()。如果您不調用setObjectName(),給線程的名稱將是線程對象的運行時類型的類名(例如,在Mandelbrot示例中,“RenderThread”是QThread子類的名稱)。請注意,目前在Windows上的版本中還不能使用這個功能。

一:Qthread成員函數介紹:

  • 共有成員函數
 

QThread(QObject *parent = Q_NULLPTR)

 

~QThread()

QAbstractEventDispatcher *

eventDispatcher() const

返回指向線程的事件調度程序對象的指針。如果線程不存在事件調度程序,則此函數返回0。

void

exit(int returnCode = 0)

告訴線程的事件循環使用返回代碼退出。
調用此函數後,線程將離開事件循環並從對QEventLoop::exec()的調用中返回。函數的作用是::exec()返回返回代碼。
按照慣例,返回碼爲0表示成功,任何非零值表示錯誤。
注意,與同名的C庫函數不同,這個函數確實返回給調用者——停止的是事件處理。

bool

isFinished() const

該信號是在相關線程完成執行之前發出的。
當發出此信號時,事件循環已經停止運行。除了延遲刪除事件之外,線程中不會處理任何事件。這個信號可以連接到QObject::deleteLater(),以釋放線程中的對象

bool

isInterruptionRequested() const

如果在此線程上運行的任務應該停止,則返回true。requestinterrupt()可以請求中斷。
此函數可用於使長時間運行的任務乾淨地可中斷。永遠不要檢查或作用於這個函數返回的值是安全的,但是在長時間運行的函數中定期這樣做是明智的。注意不要太頻繁地調用它,以保持低開銷。

bool

isRunning() const

如果線程正在運行,返回true;否則返回false。

int

loopLevel() const

返回線程的當前事件循環級別。

Priority

priority() const

返回正在運行的線程的優先級。如果線程不運行,該函數返回InheritPriority。

void

requestInterruption()

請求中斷線程。該請求是建議性的,由線程上運行的代碼決定是否以及如何響應該請求。此函數不會停止線程上運行的任何事件循環,也不會以任何方式終止它。

void

setEventDispatcher(QAbstractEventDispatcher *eventDispatcher)

將線程的事件調度程序設置爲eventDispatcher。只有在還沒有爲線程安裝事件分派器的情況下,纔有可能做到這一點。也就是說,在使用start()啓動線程之前,或者在主線程中,在實例化QCoreApplication之前。此方法擁有對象的所有權。

void

setPriority(Priority priority)

此函數設置正在運行的線程的優先級。如果線程沒有運行,這個函數什麼也不做,並且立即返回。使用start()啓動具有特定優先級的線程。
優先級參數可以是QThread:: priority enum中的任何值,繼承性優先級除外。

void

setStackSize(uint stackSize)

將線程的最大堆棧大小設置爲堆棧大小。如果堆棧大小大於零,則將最大堆棧大小設置爲堆棧大小字節,否則操作系統將自動確定最大堆棧大小。
警告:大多數操作系統對線程堆棧大小設置最小和最大限制。如果堆棧大小超出這些限制,線程將無法啓動

uint

stackSize() const

返回線程的最大堆棧大小(如果設置爲setStackSize());否則返回0。

bool

wait(unsigned long time = ULONG_MAX)

阻塞線程,直到滿足以下任一條件:

與此QThread對象關聯的線程已經完成執行(即當它從run()返回時)。如果線程已經完成,這個函數將返回true。如果線程還沒有啓動,它還返回true。
毫秒的時間已經用完了。如果時間是ULONG_MAX(默認),那麼等待將永遠不會超時(線程必須從run()返回)。如果等待超時,此函數將返回false。

二:run 方法

  •   QThreads開始在run()中執行。默認情況下,run()通過調用exec()啓動事件循環,並在線程內部運行Qt事件循環
QThread
{
class WorkerThread : public QThread
  {
      Q_OBJECT
      void run() override {
          QString result;
          /* ... here is the expensive or blocking operation ... */
          emit resultReady(result);
      }
  signals:
      void resultReady(const QString &s);
  };

  void MyObject::startWorkInAThread()
  {
      WorkerThread *workerThread = new WorkerThread(this);
      connect(workerThread, &WorkerThread::resultReady, this, &MyObject::handleResults);
      connect(workerThread, &WorkerThread::finished, workerThread, &QObject::deleteLater);
      workerThread->start();
  }

}

三:QObject::moveToThread() 方法

  • 通過使用QObject::moveToThread()將worker對象移動到線程,可以使用它。因此,希望在新線程中調用插槽的開發人員必須使用worker-object方法;不應該將新插槽直接實現到子類QThread中。這種方法;
class Worker : public QObject
  {
      Q_OBJECT

  public slots:
      void doWork(const QString &parameter) {
          QString result;
          /* ... here is the expensive or blocking operation ... */
          emit resultReady(result);
      }

  signals:
      void resultReady(const QString &result);
  };

  class Controller : public QObject
  {
      Q_OBJECT
      QThread workerThread;
  public:
      Controller() {
          Worker *worker = new Worker;
          worker->moveToThread(&workerThread);
          connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
          connect(this, &Controller::operate, worker, &Worker::doWork);
          connect(worker, &Worker::resultReady, this, &Controller::handleResults);
          workerThread.start();
      }
      ~Controller() {
          workerThread.quit();
          workerThread.wait();
      }
  public slots:
      void handleResults(const QString &);
  signals:
      void operate(const QString &);
  };

總結:

具體的一些例子官方已經給出demo:

參見Qt、QThreadStorage、同步線程、Mandelbrot示例、信號量示例和等待條件示例中的線程支持一些實例:
Thread Support in Qt, QThreadStorage, Synchronizing Threads, Mandelbrot Example, Semaphores Example, and Wait Conditions Example.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章