備注:以下僅為演示不代表合理性,適合簡單任務,邏輯簡單、臨時使用,可保持代碼簡潔,對于復雜的任務應創建一個專門的類來管理信號和線程池任務.
FileScanner類繼承QObject和QRunnable,掃描指定目錄下的文件獲取文件列表,逐個發出fileFound信號;
FileHasher:繼承QObject和QRunnable,計算文件的SHA1值,發出hashResult信號;
1、使用新建臨時對象?
#include <QCoreApplication>
#include <QThreadPool>
#include "global_threadpool_example.h"int main(int argc, char *argv[]) {QCoreApplication app(argc, argv);// 創建協調對象,處理信號QObject coordinator;// 啟動文件掃描任務FileScanner *scanner = new FileScanner("/path/to/your/directory"); // 替換為實際目錄QObject::connect(scanner, &FileScanner::fileFound, &coordinator, [&coordinator](const QString &filePath) {// 為每個找到的文件啟動SHA1計算任務FileHasher *hasher = new FileHasher(filePath);QObject::connect(hasher, &FileHasher::hashResult, &coordinator, [](const QString &filePath, const QString &hash) {qDebug() << "File:" << filePath << "SHA1:" << hash;});QThreadPool::globalInstance()->start(hasher);});QObject::connect(scanner, &FileScanner::finished, &coordinator, []() {qDebug() << "Scanning finished.";// 可選:等待所有任務完成QThreadPool::globalInstance()->waitForDone();qDebug() << "All tasks completed.";});// 提交掃描任務到全局線程池QThreadPool::globalInstance()->start(scanner);return app.exec();
}
- Qt 的信號槽機制要求信號的接收者是一個 QObject 或其派生類的實例。coordinator 是一個 QObject 實例,用于連接 FileScanner 和 FileHasher 發出的信號(如 fileFound 和 hashResult)。
- 它充當信號的“中轉站”,將任務的異步結果(例如找到的文件路徑或計算的 SHA1 值)傳遞到處理邏輯中。
-
它可以避免在 main 函數中創建額外的類或全局對象,保持代碼簡潔。
-
coordinator 是 main 函數的局部變量,其生命周期持續到程序退出。這足以處理所有信號,因為線程池任務的信號在事件循環中處理。
2、使用QCoreApplication對象
#include <QCoreApplication>
#include <QThreadPool>
#include "global_threadpool_example.h"int main(int argc, char *argv[]) {QCoreApplication app(argc, argv);// 啟動文件掃描任務FileScanner *scanner = new FileScanner("/path/to/your/directory"); // 替換為實際目錄QObject::connect(scanner, &FileScanner::fileFound, &app, [&app](const QString &filePath) {FileHasher *hasher = new FileHasher(filePath);QObject::connect(hasher, &FileHasher::hashResult, &app, [](const QString &filePath, const QString &hash) {qDebug() << "File:" << filePath << "SHA1:" << hash;});QThreadPool::globalInstance()->start(hasher);});QObject::connect(scanner, &FileScanner::finished, &app, []() {qDebug() << "Scanning finished.";QThreadPool::globalInstance()->waitForDone();qDebug() << "All tasks completed.";});// 提交掃描任務到全局線程池QThreadPool::globalInstance()->start(scanner);return app.exec();
}
QCoreApplication 是 Qt 應用程序的主對象,無需額外創建 QObject,app存在于整個程序生命周期,也可以直接用作信號槽連接的接收者,也適合信號槽邏輯簡單、臨時使用的場景。
缺點:語義上不夠清晰,因為 QCoreApplication 的主要職責是管理應用程序,而不是任務協調,如果程序中有多個模塊使用 app 處理信號,可能會導致信號槽邏輯混雜,這種方式并不推薦。
3、使用 lambda 表達式
#include <QCoreApplication>
#include <QThreadPool>
#include "global_threadpool_example.h"int main(int argc, char *argv[]) {QCoreApplication app(argc, argv);// 啟動文件掃描任務FileScanner *scanner = new FileScanner("/path/to/your/directory"); // 替換為實際目錄QObject::connect(scanner, &FileScanner::fileFound, [=](const QString &filePath) {FileHasher *hasher = new FileHasher(filePath);QObject::connect(hasher, &FileHasher::hashResult, [](const QString &filePath, const QString &hash) {qDebug() << "File:" << filePath << "SHA1:" << hash;});QThreadPool::globalInstance()->start(hasher);});QObject::connect(scanner, &FileScanner::finished, []() {qDebug() << "Scanning finished.";QThreadPool::globalInstance()->waitForDone();qDebug() << "All tasks completed.";});// 提交掃描任務到全局線程池QThreadPool::globalInstance()->start(scanner);return app.exec();
}
Qt 允許在信號連接中使用 lambda 表達式直接處理邏輯,無需顯式的接收者對象。這種方式將信號處理邏輯直接嵌入 lambda 函數中。適合信號槽邏輯簡單、臨時使用的場景。
- 代碼更簡潔,無需創建額外的 QObject,邏輯集中在 lambda 函數中,易于理解。
- lambda 表達式無法像 QObject 那樣方便地管理多個信號槽連接(例如斷開連接),而且如果 lambda 中捕獲了變量(如 [=]),特別需要注意捕獲變量的生命周期。
4、使用靜態函數或全局函數處理信號
#include <QCoreApplication>
#include <QThreadPool>
#include "global_threadpool_example.h"// 靜態函數處理信號
static void handleFileFound(const QString &filePath) {FileHasher *hasher = new FileHasher(filePath);QObject::connect(hasher, &FileHasher::hashResult, [](const QString &filePath, const QString &hash) {qDebug() << "File:" << filePath << "SHA1:" << hash;});QThreadPool::globalInstance()->start(hasher);
}static void handleFinished() {qDebug() << "Scanning finished.";QThreadPool::globalInstance()->waitForDone();qDebug() << "All tasks completed.";
}int main(int argc, char *argv[]) {QCoreApplication app(argc, argv);// 啟動文件掃描任務FileScanner *scanner = new FileScanner("/path/to/your/directory"); // 替換為實際目錄QObject::connect(scanner, &FileScanner::fileFound, handleFileFound);QObject::connect(scanner, &FileScanner::finished, handleFinished);// 提交掃描任務到全局線程池QThreadPool::globalInstance()->start(scanner);return app.exec();
}
?定義靜態函數 handleFileFound 和 handleFinished,直接連接到信號,不需要 QObject 接收者。但這種方式,靜態函數無法方便地存儲狀態(如任務列表、結果收集),不易擴展,維護性較差,僅適合信號處理邏輯非常簡單的情況。