备注:以下仅为演示不代表合理性,适合简单任务,逻辑简单、临时使用,可保持代码简洁,对于复杂的任务应创建一个专门的类来管理信号和线程池任务.
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 接收者。但这种方式,静态函数无法方便地存储状态(如任务列表、结果收集),不易扩展,维护性较差,仅适合信号处理逻辑非常简单的情况。