C++ 当运行长for循环的小部件(QDialog)在没有多线程的情况下关闭时,如何停止长for循环?

C++ 当运行长for循环的小部件(QDialog)在没有多线程的情况下关闭时,如何停止长for循环?,c++,qt,C++,Qt,我在QDialog中有一个相当长的foreach循环。基本上是这样的: foreach (xxx, xxx) { ... doSomeStuff ... QApplication::processEvents(); if (m_cancelMapLoading) { break; } } m_cancelMapLoading通过单击“取消”按钮设置为true。QApplication::processEvents();使这成为可能 这可以很好地

我在QDialog中有一个相当长的foreach循环。基本上是这样的:

foreach (xxx, xxx) {
    ... doSomeStuff ...
    QApplication::processEvents();

    if (m_cancelMapLoading) {
        break;
    }
}
m_cancelMapLoading通过单击“取消”按钮设置为true。QApplication::processEvents();使这成为可能

这可以很好地工作,但是如果对话框关闭,只要foreach循环仍然运行,它就会继续运行。我试图在关闭对话框的每个函数中将m_cancelMapLoading设置为true,但这没有帮助

我还尝试不仅测试m_cancelMapLoading是否为true,还测试isVisible()。这实际上会停止对话框,但它会立即重新打开对话框,其中没有GUI元素

不幸的是,QtConcurrent::run等不能用于函数,因为foreach循环操作的数据结构不是线程安全的


有没有一种方便的方法来解决这个问题?

将GUI从繁重的处理中卸载出来的一种非常简单的方法是将它分配给另一个或多个用户

然后,您可以轮询“should-I-terminate-yet?”变量,或者在不再需要时手动终止线程

我强烈推荐并行处理,因为它提供了更好的控制,而不是像队列清空这样的“DoEvents”。

您可以在这里使用a和Qt的父子结构。超时值为零的QTimer在Qt中有特殊意义

作为特例,超时为0的QTimer将尽快超时 因为窗口系统的事件队列中的所有事件都已 处理。这可以用来做繁重的工作,同时提供快捷的 用户界面:

所以你可以做一些像

void Dialog::beginDoingStuff()
{
    m_timer = new QTimer(this);
    connect(m_timer, SIGNAL(timeout()), this, SLOT(processData());
    m_timer->start(0);
}

void Dialog::processData()
{
    // Perform one cycle of your process here
}

这将在与对话框其余部分相同的线程中执行processData()函数,当对话框被关闭而销毁时,计时器将被删除(因为它的父对象是对话框),这意味着处理将停止。

我们实际上通过将对话框的完成信号连接到取消按钮的单击槽来解决问题。这实际上在所有情况下都会停止循环

我们还引入了通过QTimer启动函数(为了更好的实现,不阻塞函数的启动位置),但这并不会停止循环(可能是因为我们不会在对话框关闭时破坏它)


感谢所有帮助:-)

我试图通过QtConcurrent来实现,但此函数操作的数据结构不适用于多线程。这确实造成了许多问题,这些问题目前可能无法解决:-(uhm线程安全是将工作负载移动到那里所必需的。我不确定是否将此作为答案,无论如何,您应该编辑您的问题以澄清它。您是否尝试在类析构函数中将变量m_cancelMapLoading指定为true?这样做,循环将继续运行。手动推进事件循环可能导致我有点可怕的后果。试着把检查m_cancelMapLoading作为你的foreach循环的第一件事,看看这是否“修复”了事情。谢谢你的信息!我会试试这个!