在插槽中调用 QDialog::exec 会阻塞主事件循环吗?
Posted
技术标签:
【中文标题】在插槽中调用 QDialog::exec 会阻塞主事件循环吗?【英文标题】:Does calling QDialog::exec in a slot block the main event loop? 【发布时间】:2016-02-09 20:47:36 【问题描述】:我的 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()
方法时没有任何区别。
我是否阻塞了事件循环?我应该在这里使用不同的方法吗?
【问题讨论】:
据我所知,int QDialog::exec()
不会阻止 Qt 应用程序,只会阻止父窗口,并且仅当对话框是窗口模式时。
@Tarod 嗯,它是一个阻塞函数(因为它在 QDialog 关闭之前不会返回),这就是我不确定的原因。
【参考方案1】:
QDialog::exec()
阻塞了主事件循环,是的。但它不会阻止 UI,因为它会在 exec()
内部打开一个本地事件循环,该循环会在对话框打开时处理事件。这可能是令人讨厌的错误的来源:(几乎)任何事情都可能在exec()
返回之前发生,外部事件(计时器、网络、IPC 等)可以调用插槽、导致其他对话框出现等。只是用户的方式鉴于大多数此类对话框的模态性质,直接做意想不到的事情通常是有限的。
在调用exec()
时,需要注意可能的问题,不要让应用程序处于不一致的状态,也不要指望事后保持原样。
或者,调用非阻塞QDialog::open()
并连接到finished()
信号。
【讨论】:
一个后续问题 - 将 QMessageBox 与 exec() 一起使用时是否适用相同的情况?使用静态函数 API 实例化的 QMessageBox 怎么样:int ret = QMessageBox::warning... @riverofwind 以上都适用以上是关于在插槽中调用 QDialog::exec 会阻塞主事件循环吗?的主要内容,如果未能解决你的问题,请参考以下文章
在 QDialog::exec() 期间使用 QThreads 执行 QWidget::grab()