From 1890cee80190de35511c109e3007c8b97a0bdf17 Mon Sep 17 00:00:00 2001 From: ispyisail Date: Wed, 23 Sep 2026 16:20:38 +1200 Subject: [PATCH] Cancel the collection-loading map before waiting on it in ~ElementsCollectionModel Reviving #713, closed 2026-09-21 purely to clear a maintainer review backlog (#630), not on merit; not superseded. The crash #713 was originally named after (bugtracker #291) was already fixed separately by 39ac5716c, merged 14 Aug -- confirmed still on master. What's left, and what this revives, is the one-line follow-up #713 itself narrowed to after that: m_future.cancel() before the wait. Without it, ~ElementsCollectionModel()'s wait runs the whole queued QtConcurrent::map() to completion, so cancelling the open-element dialog blocks until every remaining item has been processed -- a visible hang on the button pressed precisely to stop the work. cancel() drops the not-yet-started items so the wait is short, while still waiting for whatever item is already in flight (needed so it can't dereference this object after it's gone). Qt 6.10.2, ctest 13/13. The responsiveness gain itself is reasoned from QFuture's documented cancel()/waitForFinished() semantics rather than timed -- same as the original PR's own stated verification. Co-Authored-By: Claude Sonnet 5 --- sources/ElementsCollection/elementscollectionmodel.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sources/ElementsCollection/elementscollectionmodel.cpp b/sources/ElementsCollection/elementscollectionmodel.cpp index 95af6a050..48f6176cb 100644 --- a/sources/ElementsCollection/elementscollectionmodel.cpp +++ b/sources/ElementsCollection/elementscollectionmodel.cpp @@ -49,6 +49,14 @@ ElementsCollectionModel::ElementsCollectionModel(QObject *parent) : */ ElementsCollectionModel::~ElementsCollectionModel() { + // Without cancel(), the wait below runs the whole queued + // QtConcurrent::map() to completion, so closing this dialog on a + // large collection blocks until every remaining item has been + // processed -- a visible hang on the button pressed precisely to + // stop the work. cancel() drops the not-yet-started items so the + // wait that follows (still needed, so an in-flight item can't + // dereference this object after it's gone) is short. + m_future.cancel(); m_future.waitForFinished(); }