批量执行任务:使用QtConcurrent实现

目录

批量执行一系列任务是软件中常见的需求,通常采用并行执行多个任务的方式加快速度。 比如使用下载软件下载多个文件时,下载软件会根据用户设置,同时下载队列中的几个文件,每当一个下载任务结束时,会自动启动下一个下载任务。

本文介绍如何使用 QtConcurent 实现批量执行任务的功能。下面的场景来自下载小说的软件。

方案

使用 QtConcurrent::map 执行批量任务。 QtConcurrent::map 使用全局线程池(来自QThreadPool::globalInstance)来执行程序,同时执行程序的个数由全局线程池设置的线程数决定。
同时,QtCocurrent::map 使用 QFuture 返回异步计算结果,我们可以使用 QFutureWatcherQFuture 的连接实现与任务的交互。

实现

首先设置全局线程池的线程个数,例如设置4个线程。

QThreadPool::globalInstance()->setMaxThreadCount(4);

创建对任务进行监控的 QFutureWatcher

QFutureWatcher<void> future_watcher;

准备需要批量执行的任务,比如下面下载小说章节的任务 DownloadTask

QVector<downloadTask> download_tasks_;
for(int i=0; i<novel_content_model_->rowCount(); i++)
{
    DownloadTask task;
    task.name_ = novel_content_model_->item(i, 0)->text();
    task.link_ = novel_content_model_->item(i, 1)->text();
    task.directory_ = local_directory;
    task.task_no_ = i;
    download_tasks_.push_back(task);
}

开始执行批量任务:

future_watcher_.setFuture(QtConcurrent::map(download_tasks_, [this](const DownloadTask &task){
    // 执行任务,省略代码
}));

QtConcurrent::map 会使用全局线程池自动执行所有任务。

QFutureWatcher 可以暂停或恢复任务的执行。

future_watcher_.setPaused(checked);

未来计划

上面介绍使用 QtConcurrent 可以实现简单的批量执行任务功能。 但因为 QtConcurrent 只能使用全局线程池,缺乏更精细的控制手段,所以后续计划使用自定义的 QThreadPool 实现批量下载功能。