使用QFuture实现异步监听

QtConcurrent

QFuture

QFuture 是 Qt 框架中用于表示异步计算结果的类。它是 Qt Concurrent 模块的一部分,通常与多线程编程结合使用,用于管理和获取异步任务的结果。QFuture 提供了一种方便的方式来处理并行任务,而不需要直接管理线程的创建和同步。

QFutureWatcher

QFutureWatcher提供了QFuture的信息和通知。

测试代码

#include <QtConcurrent>
#include <QFutureWatcher>
#include <QDebug>
#include <QCoreApplication>
#include <QThread>

void task() {
    qDebug() << "Task is running...";
    QThread::sleep(2); // 模拟耗时操作
    qDebug() << "Task finished.";
}

int main(int argc, char *argv[]) {
    QCoreApplication app(argc, argv);

    // 创建一个任务并运行
    QFuture<void> future = QtConcurrent::run(task);

    // 等待任务完成
    future.waitForFinished();

    // 创建 QFutureWatcher
    QFutureWatcher<void> watcher;

    // 连接 finished 信号
    QObject::connect(&watcher, &QFutureWatcher<void>::finished, []() {
        qDebug() << "QFutureWatcher: Task finished signal received.";
    });

    // 设置已经完成的 QFuture
    qDebug() << "Setting future to QFutureWatcher...";
    watcher.setFuture(future);

    qDebug() << "Main thread continues running.";

    return app.exec();
}

运行结果:

Task is running...
Task finished.
Setting future to QFutureWatcher...
Main thread continues running.
QFutureWatcher: Task finished signal received.

关键点

  • 当 QFuture 已经运行结束后,再调用 QFutureWatcher::setFuture(),仍然会触发 finished 信号。但不是立即触发

setFuture()源码

//QFutureWatcher::setFuture源码调用:
QFutureWatcher::setFuture()
->QFutureWatcherBase::connectOutputInterface();
->futureInterface().d->connectOutputInterface(d_func()) //futureInterface().d即QFuture内部指针。
->QFutureCallOutInterface->postCallOutEvent(finished)//判断QFuture已经结束后。

继续查找到QFutureWatcherBasePrivate::postCallOutEvent();

void QFutureWatcherBasePrivate::postCallOutEvent(const QFutureCallOutEvent &callOutEvent)
{
    Q_Q(QFutureWatcherBase);

    if (callOutEvent.callOutType == QFutureCallOutEvent::ResultsReady) {
        if (pendingResultsReady.fetchAndAddRelaxed(1) >= maximumPendingResultsReady)
            q->futureInterface().d->internal_setThrottled(true);
    }

    QCoreApplication::postEvent(q, callOutEvent.clone());
}

可以看到最终是通过QCoreApplication::postEvent()发送了一个事件。那么只有下次事件循环时,才会发送出finished信号。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容