【问题标题】:Dealing with application processmessages处理应用程序进程消息
【发布时间】:2015-06-03 07:35:14
【问题描述】:

在我们的软件中,我们存在异步执行事件的问题。有时一个函数会“闯入”另一个函数并产生各种奇怪的结果。

我在这里处理的是触发事件的用户输入和计时器。

问题在于,与其逐个执行与事件相关的代码,不如在 Delphi 为其提供一个窗口的第一时间完成:application.processmessages。这会产生问题,有时功能 A 的一半完成,然后功能 B “闯入”,完成,然后,功能 A 的后半部分完成。这可能会产生“令人惊讶”的结果。

有什么好的方法可以解决这个问题吗?

我尝试过的事情:

--

  • 使用“忙碌标志”,这有一些起伏,主要是你所做的一切都必须知道它。
  • 尽可能删除所有 application.processmessages。这有很好的结果。但我们依赖于一些第 3 方组件,我发现这些组件也会触发 application.processmessages。

接下来我正在考虑尝试构建某种“命令队列”,在其中我可以接收我的事件并以先进先出的方式触发它们。

除了从头开始重建我们所拥有的一切,还有其他/更好的方法来解决这些问题吗?

【问题讨论】:

  • 停止调用 ProcessMessages
  • 消除你所有的ProcessMessages,并且不要从定时器事件处理程序中调用包含ProcessMessages的第三方组件。
  • 你可以。别再叫了。
  • "Just stop call it" 可能会引入其他问题。所以我不认为这是解决所有问题的方法。用更合适的函数替换该调用。
  • @SebastianZ 那会是什么功能呢?显然,剥离对 ProcessMessages 的调用会产生后果。与他们打交道,工作就完成了。抽出消息队列并允许重新进入是一个杯子的游戏。

标签: delphi delphi-7


【解决方案1】:

最好的方法是消除对Application.ProcessMessages 的调用。大多数时候,还有其他方法可以做Application.ProcessMessages 应该做的事情。您需要仔细查看为什么需要该调用,然后找到更好的解决方案。例如,您不需要 Application.ProcessMessages 来更新 UI。还有其他方法可以做到这一点。

如果第 3 方组件正在调用 Application.ProcessMessages,请联系该供应商,让他们用更合适的函数替换此调用。如果这不是一个选项,您可以尝试使用解决方法,例如在线程中使用该组件(如果可能)。或者创建一个不可见的模态窗口,并在 ShowModal 函数内部执行组件的方法。这至少会避免用户输入消息。 (“不可见的模态窗口”是一个具有BorderStyle=bsNone,大小=1×1 和 100% 透明度的表单)。

【讨论】:

  • 您建议在线程中调用 ProcessMessages。撇开不从线程访问 VCL 对象不谈,您将抑制主线程的消息队列的泵送。 IOW,你假设第三方已经调用了 application.processmessages。这似乎不是一个合理的假设。
  • ShowModal 不会避免用户输入消息。实际上,模态循环调用 processmessage(与 processmessages 调用相同),它将检索发布的任何消息。
  • @SertacAkyuz 这些解决方法并不完美。是否可以使用取决于具体情况。 ShowModal 不会避免用户输入消息。但是模式窗口会禁用所有者窗口,并且如果上面没有可以接收输入的内容,则不会处理用户输入。并非总是可以使用线程,也并非总是解决方案。但我也看到了设计用于线程的组件,如果它们调用 ProcessMessages,它不会影响主线程。那家供应商太大了,无法投诉。
  • 如果您想要禁用所有表单,您不必摆弄不可见的表单,而是调用 disabletaskwindows。 ... 宣传用于线程的组件不应该访问 VCL 来自大供应商,这很有趣。
  • DisableTaskWindows 禁用所有窗口。但根据我的经验,最好在顶部有一个活动窗口。
【解决方案2】:

有什么好的方法可以解决这个问题吗?

首先消除您对ProcessMessages 的所有使用。正如您所发现的,当从那里调用时,它会搞砸计时器事件处理程序。在其他地方使用时,它通常会受到竞争条件的影响,可能会隐藏真正的问题。 找出问题所在并解决它

但我们依赖于一些第 3 方组件,我发现它们也会触发 application.processmessages。

Timer 事件处理程序应该只做短时间的工作。如果您通过调用计时器事件处理程序内的第 3 方库来调用 ProcessMessages,请消除该调用。除了重写库或以其他方式调用它之外,没有其他治疗方法。

除了从头开始重建我们所拥有的一切,还有其他/更好的方法来解决这些问题吗?

通常你也可以在线程中做后台工作,只要遵循不直接调用任何 VCL RTL 方法的规则。如果第 3 方组件正在调用 ProcessMessages,则此处是不可能的。


如果您无法更改第 3 方组件,则可以将消息发布到您的表单,并将调用放在处理此消息的方法中。使用现代 Delphi,您可以使用 @MasonWheeler 的 DelayedAction。但我真的建议你采取“硬”的方式来修复 3rd 方库。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-09-16
    • 1970-01-01
    • 2013-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多