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

Linux 下 Qt 多線程編程:線程類、同步機制、自定義事件與定時器替代方案

     編輯:關於C++

Qt 多線程支持概覽

Qt 從 2.2 版本提供跨平台多線程支持,三大支柱:

  1. 平台無關的線程類(QThread 等)。
  2. 線程安全的事件投遞(postEvent)。
  3. 同步原語(QMutex、QWaitCondition、QSemaphore)。

某些場景下,定時器機制可替代多線程,避免線程安全問題。

1. 平台相關的線程支持啟用

  • Windows:編譯器選項 -mt,鏈接 qt-mt 庫。
  • Unix/Linux:configure -thread,生成 libqt-mt,鏈接選項 -lqt-mt。
  • 均需定義宏 QT_THREAD_SUPPORT(Windows 在 qconfig.h,Unix 在 Makefile)。

2. 核心線程類

QThread

  • 繼承 QThread 並重寫 run() 實現線程邏輯(類似 Java Thread.run())。
  • 主線程:GUI 事件循環線程,處理窗口系統事件分發。
  • QThread::postEvent(receiver, event):從非主線程向對象投遞事件(線程安全),事件入隊後喚醒主線程分發,事件處理器在主線程執行。

QMutex

互斥鎖,保護臨界區:lock() / unlock(),支持 QMutexLocker RAII 風格。

QWaitCondition

條件變量,線程等待特定條件:wait(mutex, timeout)、wakeOne()、wakeAll()。

3. 自定義事件在多線程中的應用

步驟

  1. 繼承 QCustomEvent,構造函數傳入 Type(User + 偏移) 避免衝突。
  2. 工作線程(QThread 子類)在 run() 中創建自定義事件,調用 postEvent(receiver, event)。
  3. 接收對象(QWidget 子類)重寫 customEvent(QCustomEvent*),根據 type() 分發處理。

代碼示例

// 自定義事件
class UserEvent : public QCustomEvent {
public:
    UserEvent(QString s) : QCustomEvent(346798), sz(s) {}
    QString str() const { return sz; }
private:
    QString sz;
};

// 工作線程
class UserThread : public QThread {
public:
    UserThread(QObject* r, QMutex* m, QWaitCondition* c);
    void run() override {
        UserEvent* re = new UserEvent(resultString);
        QThread::postEvent(receiver, re);
    }
};

// 接收控件
void UserWidget::customEvent(QCustomEvent* e) {
    if (e->type() == 346798) {
        UserEvent* re = static_cast(e);
        newString = re->str();
    }
}

4. 定時器機制模擬多線程

將並發事件串行化,簡化同步,適合「處理時間短、消息頻率低」場景。

核心思路

  • 主線程創建 QTimer,連接 timeout() 信號到槽函數 slotReadFile()。
  • 槽函數中:stop() 定時器 → 讀取設備文件(Socket/FIFO) → 分發消息 → start() 重啟定時器。
  • 無消息時立即重啟;有消息則處理完畢後重啟。

示例代碼

Server::Server(QWidget* parent) : QWidget(parent) {
    readTimer = new QTimer(this);
    connect(readTimer, SIGNAL(timeout()), this, SLOT(slotReadFile()));
    readTimer->start(100);  // 100ms 周期
}

int Server::slotReadFile() {
    readTimer->stop();
    ret = read(file, buf);
    if (ret <= 0) {
        readTimer->start(100);
        return -1;
    }
    // 根據 buf 分發消息給各處理對象...
    readTimer->start(100);
    return 0;
}

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