简述
很多时候,在Qt里面需要运行一个耗时函数的时候,为了避免阻塞界面,需要放入非主线程去执行。
实现这样处理的方法有好几种,例如:
- 写一个继承自QThread类,实现run接口;
- 写一个继承自QObject的类,添加槽函数执行任务,创建对象,移入一个QThread中进行调用;
- 写一个QRunnable的子类,创建对象,添加到QThreadPool里面去调用;
上面的方法都比较麻烦些,可以使用QtConcurrent来进行简化。
这里采用基于QtConcurrent的实现,来简化这种异步调用过程,使用QEventLoop来等待执行结束,模拟同步调用。
代码
#include <QDebug>
#include <QEventLoop>
#include <QFutureWatcher>
#include <QtConcurrent/QtConcurrentRun>
#include <functional>
#include <iostream>
template<typename Func, typename... Args>
auto WaitRunAsync(Func&& func, Args&&... args) -> decltype(func(args...))
{
using ReturnType = decltype(func(args...));
// 将函数和参数绑定为一个可调用对象
auto task = std::bind(std::forward<Func>(func), std::forward<Args>(args)...);
// 使用 QtConcurrent::run 异步执行任务
QFuture<ReturnType> future = QtConcurrent::run(task);
// 创建 QFutureWatcher 来监视任务状态
QFutureWatcher<ReturnType> watcher;
if (qApp != nullptr) {
QEventLoop loop;
// 连接信号槽
QObject::connect(&watcher, &QFutureWatcher<ReturnType>::finished, &loop, &QEventLoop::quit);
// 设置 QFutureWatcher 的 future
watcher.setFuture(future);
// 使用 QEventLoop 等待任务完成
loop.exec();
}
else {
// 设置 QFutureWatcher 的 future
watcher.setFuture(future);
// 等待计算完成
watcher.waitForFinished();
}
std::cout << "event loop quit!" << std::endl;
// 返回任务结果
return future.result();
}
// 示例任务函数
int exampleTask(int a, int b)
{
std::cout << "Task is running with arguments: " << a << ", " << b << std::endl;
QThread::sleep(2); // 模拟耗时操作
std::cout << "Task completed!" << std::endl;
return a + b;
}
int main()
{
std::cout << "Main thread ID: " << QThread::currentThreadId() << std::endl;
for (int i = 0; i < 3; ++i) {
std::cout << "run task " << i << std::endl;
// 异步执行任务并等待完成,获取返回值
int result = WaitRunAsync(exampleTask, 10, 20);
std::cout << "Task result: " << result << std::endl;
}
std::cout << "Back to main thread!" << std::endl;
return 0;
}
标签:include,QFutureWatcher,args,watcher,QtConcurrent,future,Async,QFuture
From: https://www.cnblogs.com/oloroso/p/18675718