QtConcurrent命名空间非常适合简化多线程计算的管理。总的来说,这很有效,我能够以API中描述的方式使用QtConcurrent run(),map()和其他变体。
我想从QML中查询,取消()或暂停()数字密集型计算。 到目前为止,这是按照我想要的方式工作,除了我无法访问计算中的序列号。这是a link that describes a similar QML setup。
下面是我创建的小型测试应用的图片,用于封装我想要做的事情:
在上面的示例中,计算已接近完成,并且所有核心都已正常排队,从系统查询中可以看出:
但我真正想要做的是使用项目 IN THE 多线程计算本身的给定列表中的序列号。例如,一种方法可能是直接在QList或QVector中设置序列号(其他C ++ STL容器也可以正常工作),如下所示:
void TaskDialog::mapTask()
{
// Number of times the map function will be called:
int N = 5;
// Prepare the vector that we operate on with mapFunction:
QList<int> vectorOfInts;
for (int i = 0; i < N; i++) {
vectorOfInts << i;
}
// Start the calc:
QFuture<void> future = QtConcurrent::map(vectorOfInts, mapFunction);
_futureWatcher.setFuture(future);
//_futureWatcher.waitForFinished();
}
计算是非阻塞的,并且注释掉了行_futureWatcher.waitForFinished();
,如上面的代码所示。请注意,当设置为非阻塞计算时,GUI线程会响应,并且进度条会根据需要进行更新。
但是当在计算过程中查询QList容器中的值时,看起来似乎是未正确初始化数组时未预料化的垃圾值。
以下是我调用的示例函数:
void mapFunction(int& n)
{
// Check the n values:
qDebug() << "n = " << n;
/* Below is an arbitrary task but note that we left out n,
* although normally we would want to use it): */
const long work = 10000 * 10000 * 10;
long s = 0;
for (long j = 0; j < work; j++)
s++;
}
qDebug()
的输出是:
n = 30458288
n = 204778
n = 270195923
n = 0
n = 270385260
当以这种方式(非阻塞)映射计算时,n值是无用的,但总和值s
是正确的(尽管未显示)。
现在,如果我取消注释_futureWatcher.waitForFinished();
行,那么我会得到预期的值(订单无关紧要):
n = 0
n = 2
n = 4
n = 3
n = 1
但在这种情况下,启用_futureWatcher.waitForFinished();
后,我的GUI线程被阻止,进度条不会更新。
如果目标是不阻止主GUI线程,那么使用QtConcurrent :: map()启用阻塞会有什么好处呢?
其次,如何在非阻塞情况下获得n
的正确值,允许GUI保持响应并让进度条不断更新?
我唯一的选择可能是直接使用QThread,但我想在QtConcurrent中利用所有好的工具设置。
思考?建议?其他选择?感谢。
编辑:感谢用户2025983提供的帮助我解决此问题的见解。底线是我首先需要动态分配QList:
QList<int>* vectorOfInts = new QList<int>;
for (int i = 0; i < N; i++)
vectorOfInts->push_back(i);
接下来,通过取消引用指针,通过引用传递vectorOfInts
,如下所示:
QFuture<void> future = QtConcurrent::map(*vectorOfInts, mapFunction);
另请注意,mapFunction的原型保持不变:
void mapFunction(int& n)
然后一切正常:GUI保持响应,进度条更新,n
的值都正确等等,无需通过函数添加阻止:
_futureWatcher.waitForFinished();
希望这些额外的细节可以帮助其他人。
答案 0 :(得分:1)
这里的问题是当mapTask()
完成时你的QList超出了范围。
由于mapFunction(int &n)
通过引用获取参数,因此它引用整数值,这些值现在是超出范围的数组的一部分!那么计算机就可以随意使用那个内存做任何事情,这就是你看垃圾值的原因。如果你只是使用整数参数,我建议按值传递参数,然后一切都应该有效。
或者,如果必须通过引用传递,则可以让futureWatcher在完成时删除该数组。
QList<int>* vectorOfInts = new QList<int>;
// push back into structure
connect(_futureWatcher, SIGNAL(finished()), vectorOfInts, SLOT(deleteLater()));
// launch stuff
QtConcurrent::map...
// profit