在取消线程上使用 QFuture 释放内存
Posted
技术标签:
【中文标题】在取消线程上使用 QFuture 释放内存【英文标题】:Free memory using QFuture on cancel thread 【发布时间】:2018-07-11 11:01:23 【问题描述】:我正在编写一个使用QtConcurrent
启动线程的程序。就我而言,当我使用鼠标滚动时,我使用它来呈现 QGraphicsView。
我正在使用以下代码启动线程:
if (future.isRunning())
future.cancel();
future = QtConcurrent::run(this,&AeVectorLayer::render, renderparams, pos);
watcher.setFuture(future);
当线程完成时,我用QfutureWatcher
捕获信号finished
。
这是我的渲染函数:
QList<AeGraphicsItem*> AeVectorLayer::render(Ae::renderParams renderparams, int pos)
AeVectorHandler *coso = new AeVectorHandler();
coso->openDataset(AeLayer::absoluteFilePath);
coso->setTransformCoordinates(myEPSG);
QList<AeGraphicsItem*> bla = coso->getItems(renderparams.sceneRect.x(),
renderparams.sceneRect.y(), renderparams.sceneRect.width(),
renderparams.sceneRect.height(), renderparams.zoom, color, this);
for (int i = 0; i < bla.size(); i++)
bla.at(i)->setZValue((qreal)pos);
delete coso;
return bla;
如您所见,我的渲染函数中有一个QList<QGraphicsItem*>
。当未来被取消时,我怎样才能销毁这个列表?我不明白在我的代码中我正在重新定义 future
变量,但我不知道如何避免它。
【问题讨论】:
根据documentationQFuture
返回的QtConcurrent::run
可以不被取消。
@G.M.是的,我知道这一点。但是当您使用 cancel() 方法时,您可以在线程完成时从 QFutureWatcher 接收 Canceled() 事件。我的问题是我丢失了对已取消线程的引用,我无法接收此事件。在这种情况下,我可以删除 QList 并避免内存问题。
您需要提供更多信息。谁或什么负责bla
中的AeGraphicsItem *
项目的所有权?还有,为什么coso
分配在free store而不是stack上?
@G.M. coso
分配在免费商店,因为仅用于使用 OGR 打开 shapefile (*.shp) 并将我的几何列表转换为 QGraphicsItem
【参考方案1】:
停止尝试手动管理内存,而是使用适合您用例的智能指针。因为您使用不知道移动的QFuture
,所以您需要一个std::shared_ptr
。一旦QFuture
/QFutureWatcher
s 超出范围,并且您不再持有shared_ptr
实例,该资源将被删除。所以在你的情况下,你的render
函数应该返回一个QList<std::shared_ptr<AeGraphicsItem>>
。当您将所有权从shared_ptr
s 转移到例如QGraphicsScene
:所有权转让时,您必须从shared_ptr
release
。
请注意,您的isRunning
检查后跟cancel
存在根本缺陷:未来可能在您调用isRunning
时运行,但在您调用cancel
时完成。如果您想取消它,只需致电cancel
。另请注意,您无法有意义地取消 QtConcurrent::run
返回的 QFuture
s,因此您所做的事情本身就是非常非常错误的。
【讨论】:
我尝试使用它,但无法很好地运行该程序。我决定使用一个继承自 QThread 的类并实现我自己的 Cancel() 方法。感谢您的帮助。以上是关于在取消线程上使用 QFuture 释放内存的主要内容,如果未能解决你的问题,请参考以下文章