在插槽中调用 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()
信号。
我的 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()
信号。