如果在没有多线程的情况下关闭运行它的小部件(QDialog),我怎么能停止长循环?

时间:2014-11-03 21:28:22

标签: c++ qt

我在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循环操作的数据结构不是线程安全的。

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

3 个答案:

答案 0 :(得分:1)

您可以在此处使用QTimer和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()函数,并且当对话框被关闭时销毁时,将删除计时器(因为它的父对象是对话框),这意味着处理将停止。

答案 1 :(得分:0)

从繁重的处理中卸载GUI的一种很好且非常简单的方法是将其分配给另一个threadQtConcurrent

然后你可以轮询一个" should-I-terminate-yet?" 变量,或者在不再需要时手动终止该线程。

我强烈推荐并行处理,因为它提供了更好的控制,而不是像#E; DoEvents"类似的队列清空。

答案 2 :(得分:0)

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

我们还介绍了通过QTimer启动函数(为了更好的实现而不阻塞它启动的函数),但这并不会停止循环(也许是因为我们不会在关闭时销毁对话框)。

感谢您的帮助: - )