自定义创建QFuture
Custom creation of QFuture
我在QtConcurrent
中遇到了一个非常奇怪的问题,主要是因为奇怪的编程欲望,也许这只是一个XY问题,但。。。
所以,这是我的代码,试图与数据库通信,实际上是一个后端代码(在Qt上,是的(。它必须快速工作并处理一些请求,所以我需要一个线程池。众所周知,我认为建立连接本身是一项非常耗时的操作,因此需要持久的数据库连接来产生持久的线程(QSqlDatabase
不能在线程之间移动(。此外,想要异步请求处理也是很自然的,因此需要一种简单的方法将它们传递给持久线程。
没有什么太复杂的,让我们假设已经存在一些类似。。。
// That's what I want for now
QFuture<int> res = workers[i]->async(param1, param2);
// OR
// That's what I DO NOT want to get
workers[i]->async(param1, param2, [](QFuture<int> res) { // QFuture to pass exceptions
// callback here
});
这是可以肯定的。为什么不std::future
?好吧,使用QFutureWatcher
要容易得多,它是通知结果准备就绪的信号。纯C++通知解决方案muuuch更为复杂,回调也需要在类层次结构中拖动。显然,每个工作线程都用DB连接来连接线程。
好吧,所有这些都可以写出来,但是。。。自定义线程池将意味着没有QtConcurrent
的便利性,创建QFuture
以便由自定义工作程序返回似乎只有风险的方法。QThreadPool
没有用,因为在其中创建持久的可运行程序将是一个大故事。更重要的是,我简要描述的样板将是某种项目的核心,在许多地方使用,而不是一个100个手工线程可以轻易取代的东西。
简而言之:如果我能为我的结果构造一个QFuture
,问题就会解决。有人能给我指一个解决方案或变通办法吗?如果有什么好主意,我将不胜感激。
UPD:
@VladimirBershov提供了一个很好的实现观察者模式的现代解决方案。经过一些谷歌搜索,我发现了一个QPromise库。当然,构建一个自定义的QFuture
仍然很麻烦,只能通过未记录的QFutureInterface
类来完成,但据我所判断,仍然有一些"类似承诺"的解决方案使异步调用更加整洁。
您可以使用AsyncFuture库作为自定义QFuture
创建工具或创意来源:
AsyncFuture-像Promise对象一样使用QFuture
QFuture与QtConcurrent一起用于表示异步计算。它是多线程编程。但它的使用仅限于线程,它不适用于QObject。通过Q未来观察者。
AsyncFuture旨在增强功能,以提供更好的方式将其用于异步编程。它提供了Promise对象类接口。这个项目的灵感来自AsynQt和RxCpp。
功能:
- 将来自QObject的信号转换为QFuture对象
- 将不同类型的多个期货组合为一个期货对象
- 像Promise对象一样使用Future
- 可链接回调-高级多线程编程模型
将来自QObject的信号转换为QFuture对象:
#include "asyncfuture.h"
using namespace AsyncFuture;
// Convert a signal from QObject into a QFuture object
QFuture<void> future = observe(timer, &QTimer::timeout).future();
/* Listen from the future without using QFutureWatcher<T>*/
observe(future).subscribe([]() {
// onCompleted. It is invoked when the observed future is finished successfully
qDebug() << "onCompleted";
},[]() {
// onCanceled
qDebug() << "onCancel";
});
我的想法是使用线程池,每个线程最多可使用1个线程。
QThreadPool* persistentThread = new QThreadPool; // no need to write custom thread pool
persistentThread->setMaxThreadCount(1);
persistentThread->setExpiryTimeout(-1);
然后
QFuture<int> future_1 = QtConcurrent::run(persistentThread, func_1);
QFuture<int> future_2 = QtConcurrent::run(persistentThread, func_2);
func_2
将在func_1
之后在同一个"持久"线程中执行。
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- 使用std::multimap迭代器创建std::list
- 在全局变量中保存类的实例以重新创建类(创建"backup")
- 使用CMake创建QML插件
- 如何在c++中为模板函数实例创建快捷方式
- 在C++中,是否可以基于给定的标识符创建基类的新实例,反之亦然
- 创建一个函数以在输入为负数或零时输出字符串.第一次执行用户定义的函数
- OpenCV EqualizeHist()从彩色图像创建黑白图像
- 试图在visual studio上用C++创建一个桌面应用程序
- std::threads可以从Windows DLL中的全局变量创建/销毁吗?
- 如何在C++20中创建模板别名的推导指南
- 如何为模板化对象创建模板向量?VS正在投掷C3203
- 如何创建一个空的全局类并在启动时实例化它
- 无法创建抽象类的实例
- 链接到自行创建的dll失败
- 为什么我不能在不创建字符串变量的情况下使用函数的字符串输出
- 自定义创建QFuture
- Qt - 如何从线程创建 QFuture
- QFuture 无法为位于不同线程中的父线程创建子级
- Q等待条件,手动复位除外?(或者在Qt Concurrent之外创建QFuture对象?)