我在网上找到了一些参考资料,人们说这不起作用,但他们从来没有给出为什么这不起作用的解释。
在伪代码中,我是这样做的:void MyObject::doWork() {
QList<Item *> worklist;
for ( int i = 0; i < nitems; i++ ) {
Item *item = getItem(i);
if (item->isVisible()) {
worklist.prepend(item);
} else {
worklist.append(item);
}
}
QtConcurrent::map(worklist, procfunc);
}
本质上,创建一个要处理的对象列表,并将更重要的对象放在列表的前面。然后处理每个项目,希望利用系统中有多少核心。
我可以打印worklist
的内容,它包含了一堆看起来很合理的指针。我可以遍历列表,在每个项目上显式地调用QtConcurrent::run
,这很好地工作了。
与QtCuncurrent::map
接口,procfunc
不得到指针,它得到一些随机数据。我尝试了procfunc
的两种不同声明(没有警告,它告诉您有关此接口的类型安全的一些信息):
static void profunc(Item *);
static void profunc(Item *&); // Probably correct given the API definition
所有的例子都创建了一个对象列表,而不是指向对象的指针。这些对象通常实现Qt的"写时复制"语义,但这在我的应用程序中并没有多大意义。
这可能吗?如果是这样,我做错了什么?如果不是,有人能解释一下发生了什么使这成为不可能吗?
如果你仔细阅读的话,文档中是这么说的。有两个类似的接口,QtConcurrent::map和QtConcurrent::mapped:
QtConcurrent::mapped()接受一个输入序列和一个映射函数。然后对序列中的每一项调用这个映射函数包含映射函数返回值的新序列为返回。
…
这里的关键短语是,这会修改序列。如果你想就地修改序列,使用QtConcurrent::map()。
我最初的读取是"map"修改了对象的位置,而"mapped"生成了对象的新副本…但事实上,在这些接口中不同的是顺序,而不是对象。在我的代码中,序列脱离了作用域,因为我假设它是在QtConcurrent内部处理的,但由于我使用的是应该在适当位置修改序列的接口,因此不可能是真的。因此所有的虚假数据。
这意味着这是错误的API的工作,我试图做的
如果Item有成员函数void Item::procMyself()
然后将其包装为void procfunc(Item*& item) { item->procMyself();}
,并使用QtConcurrent::map(worklist, procfunc);
如果你只有void procThat(Item* item)
,把它包装成void procfunc(Item*& item) { procThat(item);}