当事情已经很忙时防止计时器运行(使用Qt)

Posted

技术标签:

【中文标题】当事情已经很忙时防止计时器运行(使用Qt)【英文标题】:Preventing timers from running when something is already busy (using Qt) 【发布时间】:2011-03-31 10:19:33 【问题描述】:

在我的数学应用程序中,我使用计时器来定期执行某些操作。这些操作也可以由我的用户配置。现在,如果已经有另一个动作忙,我不希望执行这些动作。

例如如果用户刚刚通过选择菜单项开始了复杂的计算,我不想执行我的计时器后面的操作。

问题是用户可以通过许多不同的方式执行操作(通过菜单、通过单击某处、通过弹出菜单、通过拖放,...)。如果应用程序当前不在主事件循环中,我实际上想要的是防止计时器关闭。

我会举一个更具体的例子来说明清楚:

在启动时我会创建计时器 如果计时器关闭,我会执行一些操作,这些操作实际上可以访问应用程序数据结构中的几乎所有位。 现在假设用户启动了一个数学算法(通过菜单、单击或拖动屏幕上的元素,不管他是如何启动它的)。 算法将执行大量计算(在主线程中)。由于它们在主线程中执行,因此计时器事件不会发生。 现在算法会显示一个消息框(可能是警告或问题)。 当消息框打开时,会再次处理事件,包括我的计时器事件,这可能会执行不正确的计算,因为已经有另一个算法在运行。

目前无法重新设计我的应用程序,以便将逻辑移至单独的工作线程,或者对我的所有操作添加检查。所以请不要建议完全修改我的应用程序。

到目前为止,我尝试了以下内容:

使用postEvent发送事件,希望这个事件只在主事件循环中执行。不幸的是,消息框的事件循环似乎也在处理已发布的事件。 使用 QEvent::WindowBlocked 和 QEvent::WindowUnblocked 事件查看模式对话框何时打开。在我的计时器事件逻辑中,我可以检查我们是否在 QEvent::WindowBlocked-QEvent::WindowUnblocked 调用之间。不幸的是,这些事件仅适用于 Qt 本身创建的模式对话框,不适用于其他对话框(例如 Windows 消息框或系统的打印机配置对话框)。此外,如果子例程会创建其他事件循环,此技巧也无济于事。

我真正需要解决我的问题是一个简单的功能,即:

如果应用程序正在处理主事件循环中的事件,则返回 true 如果应用程序正在另一个 [sub] 事件循环中处理事件,则返回 false

另一种方法是返回一个级别,指示所处理事件的“深度”。

有人建议吗?

【问题讨论】:

这可能正是您不想要的建议,但这种情况似乎需要对您的数据进行互斥保护。本质上,您有多个线程访问相同的数据;所以使用互斥锁来确保一次只有一个线程可以执行此操作。 这是单线程的。重新进入是由于创建新事件循环的例程中的阻塞调用。使用互斥锁会导致系统死锁。 【参考方案1】:

您可以使用 QAbstractEventDispatcher 挂钩到主线程/应用程序的事件循环。根据您的应用程序状态有条件地过滤掉 QTimer 事件。

【讨论】:

但这要求我的应用程序中的每个操作都设置一个全局应用程序状态。 如果您不能明确设置应用程序状态,您也许可以以某种方式推断它。在我看来,这种应用程序状态的定义是不可避免的:要么你的应用程序准备好处理用户命令,要么没有。

以上是关于当事情已经很忙时防止计时器运行(使用Qt)的主要内容,如果未能解决你的问题,请参考以下文章

防止计时器在后台模式下暂停

如何使用 pushViewController 方法防止计时器重置?

九QT实现计时器-从设计到打包运行

九QT实现计时器-从设计到打包运行

刷新网页时如何防止倒数计时器重置?

当工作忙时咋办,同一个时间干同一个事