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

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

我的 Qt 应用程序的主要 window 是一个普通的 QMainWindow 子类。在那 window 我有几个按钮;每个都有自己的 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 作者说

you should never ever block the event loop

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

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

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

人们需要意识到可能存在的问题,并且在调用 exec() 时不要让应用程序处于不一致的状态,并且不要依赖于事后的状态。

或者,调用非阻塞 QDialog::open() and connect to the finished() 信号。