【发布时间】:2015-02-07 00:29:44
【问题描述】:
我的 Delphi 应用程序有 2 个活动(似乎)都必须在 UI 线程中发生。在大多数方面,它是一个单线程应用程序。我在这里遇到了部分问题,因为我使用了 Application.ProcessMessages,并且我确实希望尽量减少它,因为它可能会导致问题。
我会先描述成分,然后描述问题。
该应用程序可以打开多个“文档”表单,但为简单起见,我将仅引用一个文档表单。每个表单都可以与外部设备通信。
在某些情况下,程序被构建为循环,直到设备的某种情况允许我们退出循环或用户取消操作。设备接口没有线程,必须轮询。
问题来了:
当用户想要关闭文档时,我们可能处于其中一个循环中。这是一个问题,因为所有这些都在 UI 线程中......我没有一个好的方法来打破文档表单中的循环,以便我可以关闭文档。
虽然没有(DeviceReady 或 CancelKeyPressed)做 Application.ProcessMessages;
原解决方案:
我最初的解决方案是在用户尝试关闭文档时执行以下操作:
- 向文档表单发布一条用户 Windows 消息,告诉它我们要关闭。
- 文档表单接收到消息并中断任何活动循环并将消息发送回主表单,说明我们已准备好关闭。
- 主窗体循环、处理消息并轮询检查文档是否已准备好关闭。
- 当文档准备关闭时,它将完成文档的关闭。
这在大多数情况下都有效,但它很复杂——尤其是因为我们同时打开了多个文档。
其他可能的解决方案
因为在我看来,所有这些都必须发生在主线程中,将其移至线程听起来不是一个解决方案。
曾想过让文档异步关闭,但我们需要知道文档关闭何时完成,以便让用户执行其他操作,例如打开另一个文档。
循环非常快; 1)发送“停止”消息 2)等待___毫秒并处理消息以使其工作 3)关闭它。我认为这将是一个低质量的设计,会很弱。
将此循环转换为状态机。 (旧版)设备接口没有线程,必须轮询。我需要创建一个线程来进行轮询并将消息发布到表单以引发事件。然后,如果发生此类事件或按下某个键,则会发生一个事件,该事件将导致下一个状态发生。这样,如果要关闭表单,就不会成为问题。遗憾的是,需要努力将周围的代码也转换为参与状态机。 (这还不错。)
结论
Application.ProcessMessages 似乎是一种药物...开始使用它,很快您就需要更多地使用它!
任何人有任何建议如何更好地处理此类问题?
回答您的问题:
(我发布这个问题是为了获得一些关于我应该采取哪种方式的意见;我是一名单独工作的开发人员,因此向社区寻求一些明智的建议是有意义的......)
感谢您的 cmets!
如何管理/引用这些“文档”?
文档表单是对象列表拥有的标准 delphi TForm 后代。
多线程的规则是,如果你需要一个连续的循环,可能导致主线程没有响应,它应该是线程的形式。为什么不允许你把它放在其他地方?为什么一定要在主线程中?
问题是整个应用程序需要等到操作完成或被用户取消。我想我可以将所有传入的键传递给线程。当线程看到循环退出条件满足时,它可以通知 UI 线程。
我喜欢状态机方法。
我也是...它具有一定的优雅和简洁。它还可以简化一些其他相关系统。
为什么不能从线程中与“设备”对话?我会从 UI 中打破那部分。
也许这就是我应该做的。我需要的唯一调用是线程安全的。
很多时候人们可能会告诉您,为了提高性能而将内容移动到线程中是一个常见的错误。但这是你为什么应该这样做的一个主要例子。我无法想象任何严格需要主 UI 线程的界面。您是否在表单设计器中使用组件?如果这是您的挫折,您是否尝试过在不同的线程中动态创建这些组件?
组件包括一个功能区,是的,所有组件都是从 UI 线程创建的。假设我无法在另一个线程中安全地创建组件并将它们放在用户将与之交互的表单上。这肯定不能正常工作吗?
我有足够的线程经验,我实际上可以做到这一点,但我想更确定我没有遗漏什么明显的东西。
【问题讨论】:
-
这很难理解,因为我看不到你的代码。您目前如何执行此“循环”?这些“文档”是如何管理/引用的?多线程的规则是,如果你需要一个连续的循环,可能导致主线程没有响应,它应该是线程的形式。为什么不允许你把它放在其他地方?为什么一定要在主线程中?
-
我喜欢状态机方法。
-
为什么不能从线程中与“设备”对话?我会从 UI 中打破这部分。
-
很多时候人们可能会告诉你,为了提高性能而将内容移动到线程中是一个常见的错误。但这是你为什么应该这样做的一个主要例子。我无法想象任何严格需要主 UI 线程的界面。您是否在表单设计器中使用组件?如果这是您的挫折,您是否尝试过在不同的线程中动态创建这些组件?
-
感谢大家的cmets!我采取了不同寻常的步骤,在问题本身的末尾回复他们。我认为共识是最好使用线程或状态机来完成。我需要深入研究并做出选择。谢谢大家!
标签: delphi user-interface