delphi - 如何捕获 TDataModule.OnCreate 事件中的异常?

标签 delphi exception

我在 Delphi 中使用 try/except block 遇到了以下问题。

我有一个简单的应用程序 - 一个名为 fr_MAIN 的 MainForm 和一个名为 DMTDataModuleDM 不是自动创建的,而是在运行时在 fr_MAINButton2.OnClick 事件中创建的:

procedure Tfr_MAIN.Button2Click(Sender: TObject);
begin
  try
    DM := TDM.Create(nil);
    Showmessage('DM started!');
  except
    on E:Exception do
    begin
      Showmessage('DM not started!');
    end;
  end;

DM 在其 OnCreate 事件中有一些代码:

procedure TDM.DataModuleCreate(Sender: TObject);
begin
  raise Exception.Create('this is error!');
  // DM code here ...
end;

问题是,当我点击Button2时,我收到“这是错误!”异常消息,其余的DM代码在这里 不运行 - 这是正确的!但随后我还收到 'DM started!' 消息,而不是 'DM not started!' 消息。

DM 引发的异常会中断操作,但不会在表单的 except block 中捕获!

这是为什么?

最佳答案

TDataModule1OnCreate 事件中引发的异常进行特殊处理。

异常处理在这里:

procedure TDataModule.DoCreate;
begin
  if Assigned(FOnCreate) then
  try
    FOnCreate(Self);
  except
    if not HandleCreateException then // <-- here
      raise;
  end;
end;

function TDataModule.HandleCreateException: Boolean;
begin
  if Assigned(ApplicationHandleException) then
  begin
    ApplicationHandleException(Self); // <-- here
    Result := True;
  end
  else
    Result := False;
end;

默认情况下,TApplicationTApplication.HandleException() 分配给 ApplicationHandleException:

constructor TApplication.Create(AOwner: TComponent);
var
  ...
begin
  inherited Create(AOwner);
  ...
  if not Assigned(System.Classes.ApplicationHandleException) then
    System.Classes.ApplicationHandleException := HandleException; // <-- here
  if not Assigned(System.Classes.ApplicationShowException) then
    System.Classes.ApplicationShowException := ShowException;
  ...
end;

因此,TDataModule.DoCreate() 捕获异常并将其传递给 TApplication.HandleException(),然后默认显示一个弹出对话框。由于 TDataModule.HandleCreateException() 返回 True,因此不会重新引发捕获的异常。该异常现在被视为已处理,允许程序正常继续其 Showmessage('DM started!'); 调用。

为了避免引发异常时弹出对话框,您可以分配一个 TApplication.OnException 事件处理程序:

Vcl.Forms.TApplication.OnException

Use OnException to change the default behavior that occurs when an exception is not handled by application code. The OnException event handler is called automatically in the HandleException method.

但是异常仍然会被 TDataModule.DoCreate() 捕获并消除。如果您想避免这种情况,让异常沿着调用堆栈向上传播,则根本不要从 TDataModule.OnCreate 事件引发异常。重写虚拟 TDataModule.Create() 构造函数并从那里引发异常。

1:同样的事情也发生在 TCustomForm 中。

关于delphi - 如何捕获 TDataModule.OnCreate 事件中的异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47043719/

相关文章:

mysql - 在 Delphi 中过滤 MySQL 结果

delphi - 如何创建一个行为类似于 Tpanel 的 TCustomControl?

delphi - 如何在 TMemo 中突出显示一行?

ruby-on-rails - 防止 FloatDomainError NaN

c# - SaveAs 方法配置为需要有根路径,而路径 '~\\images\\594083964.jpg' 没有根

delphi - Delphi:防止TPageControl提示显示在包含的项目上

delphi - 如何在twebbrowser上的框架中填充任何字段?

exception - JavaFX:无法设置绑定(bind)值异常

java - 当我期望代码简单地打印 "Error"时,为什么我的代码会抛出 ArithmeticException ?

尝试显示数组时发生 Java 异常