首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Qt 多執行緒開發:QThread 常見坑與對象生命週期管理

     編輯:關於C語言

前言:為何需要多執行緒?

當使用者點擊按鈕觸發耗時操作(如網路請求、大量運算)時,若直接在主執行緒執行,介面會凍結無響應。此時必須將耗時任務移至子執行緒,保持主執行緒(UI 執行緒)流暢。

常見錯誤範例分析

網路上流傳的一種「移動對象到執行緒」寫法如下:

QThread pingThread;
QObject::connect(&obj, SIGNAL(sig()), this, SLOT(getData()), Qt::QueuedConnection);
Dummy dummy;
obj.moveToThread(&pingThread);
QObject::connect(&dummy, SIGNAL(sig()), &obj, SLOT(pingIp()), Qt::QueuedConnection);
pingThread.start();
dummy.emitsig();

這段碼看似可行,實則隱藏嚴重隱患:

  • 執行緒對象生命週期問題:若 pingThread 是區域變數,函式結束時會被析構,但子執行緒可能仍在運行,導致程式崩潰。
  • 跨執行緒訊號槽連線類型未指定:預設 Qt::AutoConnection 在跨執行緒時行為不確定,必須顯式使用 Qt::QueuedConnection。
  • 資料回傳機制缺失:槽函式無返回值,需透過成員變數或訊號傳回結果。

正確做法:成員變數持有執行緒與工作對象

// 標頭檔中宣告為成員
QThread *workerThread;
WorkerObject *workerObj;

// 建構時初始化
workerThread = new QThread(this);
workerObj = new WorkerObject();
workerObj->moveToThread(workerThread);

// 連線:工作完成發訊號回主執行緒
connect(workerObj, &WorkerObject::finished, this, &MainClass::onWorkFinished, Qt::QueuedConnection);
// 啟動執行緒
workerThread->start();
// 觸發工作
QMetaObject::invokeMethod(workerObj, "doWork", Qt::QueuedConnection);

訊號槽連線類型詳解

連線類型行為適用場景
Qt::DirectConnection立即同步呼叫槽函式同一執行緒、需即時回應
Qt::QueuedConnection將槽呼叫放入接收方執行緒事件佇列跨執行緒通訊首選
Qt::BlockingQueuedConnection同步阻塞等待槽執行完畢需等待結果的跨執行緒呼叫
Qt::AutoConnection自動判斷(同執行緒 Direct,跨執行緒 Queued)一般情況,但跨執行緒建議顯式指定

核心原則總結

  1. 執行緒對象(QThread)必須比工作對象活得久,建議設為類成員或 new 並指定 parent。
  2. 工作對象(QObject 子類)moveToThread 後,其槽函式在該執行緒執行。
  3. 跨執行緒訊號槽務必指定 Qt::QueuedConnection,確保線程安全。
  4. 資料傳遞用訊號帶參數,避免共享記憶體造成競爭。

本文轉載自 “賣萌程式設計師” 博客,原文出處:https://7677869.blog.51cto.com/7667869/1288018

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved