delphi - 如何优雅地退出在 Delphi 中执行代码的 MDI 表单

标签 delphi error-handling mdi

我有一个用 Delphi 2007 编写的 MDI 应用程序。

如果用户在执行代码时退出其中的表单,则会导致异常,因为代码正在尝试更新组件或使用已随表单释放的对象。

无论如何我可以判断代码是否在退出事件中执行,或者是否有处理这种情况的标准方法?

更新更多信息

异常通常发生在以下情况。

子 mdi 表单上的一个按钮被按下,这将激活表单中的一个功能,该功能将进入数据库并检索数据,然后它将重新格式化并将其显示在表单上的可视组件中(可用 TListView )。

如果代码需要很长时间执行(例如,如果有大量数据要处理),用户将失去兴趣并单击关闭按钮(代码的速度已被努力避免这种情况)。

即使它所属的表单已被释放,函数内的代码仍在执行(代码位于表单的私有(private)部分),现在当它尝试更新它们不再存在的可视组件时(因为它们被释放了表单),它会引发异常。

发生这种情况时,子表单中的代码可以在循环中使用,循环记录并相应地更新 ListView ,循环包含看起来像这样的代码

inc(i);
if (i mod 25) = 0 then
begin
    StatusPnl.Caption := 'Loading ' + intToStr(i) + ', Please wait';
    application.ProcessMessages;
end;

其他代码示例

fromClose 事件看起来像这样
//Snip
if (Not (Owner = nil)) then
with (Owner as  IMainForm)do
begin
    //Snip
    DoFormFree(Self,Self.Name);
end
else
//Snip

DoFormFree 是主 mdi 父窗体中的一个函数,看起来像这样
//Snip
(G_FormList.Objects[x] as TBaseForm).Release;
G_FormList.Objects[i] := nil;
G_FormList.Delete(i);
//Snip

由于各种原因,所有表单都存储在一个列表中,并且所有子表单都扩展了 TBaseForm 类。

理想情况下,我想要一种方法来判断表单中的代码是否正在执行,并防止用户关闭表单,或者在代码完成之前隐藏它,因为在某些情况下,它可能会生成报告并更新为状态面板发生异常,在这种情况下,报告将不完整。

由于所有表单都是 TbaseFrom 的子类,因此某种全局方式这样做是理想的,因此我可以将代码添加到基本表单并使其适用于所有下降的表单。

最佳答案

您提供的信息不足,但想到的最简单的解决方案是在 OnCloseQuery 处理程序中测试代码是否正在执行,如果是,请将 CanClose 设置为 False。

或者,您可以通过创建表单和后台代码都知道的中间对象来将代码与 MDI 表单分离。你让它有一个对表单的引用,当表单关闭时它会被重置。通过此中间对象路由对表单的所有访问,您可以防止异常。

编辑:您需要提供有关在释放 MDI 表单后如何执行尝试访问 MDI 表单的代码的信息。有一些方法可以执行工作代码,例如:

  • 在形式或另一个对象的方法中
  • 在 OnTimer 事件处理程序中
  • 在 Application 对象的 OnIdle 处理程序中
  • 在后台线程中

  • 请注意,在第一种情况下,只有在您自己在代码中执行此操作或调用 Application.ProcessMessages 时才能释放表单。如果没有有关您的代码外观的更多信息,没有人可以为您的问题提供具体答案。

    编辑 2:通过您添加的信息,似乎有问题的代码总是以表单的方法执行。这很容易通过创建一个 bool 成员来捕获,该成员在执行开始时设置为 True,在执行完成时设置为 False。现在您只需在基类中为 OnCloseQuery 添加一个处理程序,如果成员(例如 fExecuting)为 True,则将 CanClose 设置为 False。您可以静默禁止关闭,或显示信息框。我只是在状态栏中显示进度表或显示某些内容,以免使用模式信息框过多地打扰用户。

    我肯定会做的是允许用户取消长时间运行的过程。因此,您还可以显示一个消息框,询问用户是否要取消操作并关闭。您仍然需要跳过关闭表单,但可以存储关闭请求,并在执行结束后处理它。

    关于delphi - 如何优雅地退出在 Delphi 中执行代码的 MDI 表单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/479208/

    相关文章:

    C# WinForms : How do you prevent child form from being minimized when parent form is minimized?

    .net - 以编程方式指定要加载的 .NET 版本

    delphi - 如何将 WriteLn 与枚举类型一起使用?

    delphi - 如何在运行时在主题和非主题之间切换应用程序?

    .net - 为什么发生异常时不显示stacktrace?

    ios - 在基于 UIDocumentBrowserViewController 的应用程序中打开多个文档

    delphi - 如何在delphi中同时播放多个.wav文件

    error-handling - RxJS HTTP请求错误处理

    jquery - jQuery AJAX XMLHTTPRequest在错误状态下没有有用的信息

    c# - 防止 MVVM/MDI 应用程序中几乎重复的 RelayCommands