在插槽中调用QDialog::exec是否会阻塞主事件循环

Does calling QDialog::exec in a slot block the main event loop?

本文关键字:循环 事件 exec 插槽 调用 QDialog 是否      更新时间:2023-10-16

我的Qt应用程序的主窗口是一个普通的QMainWindow子类。在那个窗户里我有几个按钮;每个都有自己的clicked信号连接到自己的插槽,每个插槽创建一个不同的QDialog,如下所示:

void onButtonA_clicked()
{
    MyADialog* dialog = new MyADialog(this);
    dialog->exec();
    delete dialog;
}

我一直在读这篇文章:https://wiki.qt.io/Threads_Events_QObjects#Events_and_the_event_loop作者说

你永远不应该阻止事件循环

这让我很担心;exec是一个阻塞函数,所以根据他在那里所说的(他用Worker::doWork的例子做了很多工作,需要一些时间来完成),我的代码正在阻塞事件循环,但我没有注意到任何可能表明这一点的东西;相反,主窗口的行为似乎正常,当我将代码更改为使用show()方法时没有什么不同。

我是否阻止了事件循环?我应该使用不同的方法吗?

QDialog::exec()阻止主事件循环,是的。不过,它并没有阻塞UI,因为它在exec()内部打开了一个本地事件循环,该循环在对话框打开时处理事件。这可能是严重错误的来源:(几乎)在exec()返回之前,任何事情都可能发生,外部事件(定时器、网络、IPC等)可能会调用插槽,导致其他对话框出现,等等。考虑到大多数此类对话框的模态性质,用户直接做意外事情的方式通常是有限的。

需要意识到可能的问题,在调用exec()时不要让应用程序处于不一致的状态,也不要依赖于之后的情况。

或者,调用非阻塞QDialog::open()并连接到finished()信号。