如何在TDataModule.OnCreate事件中捕获异常?

alt*_*ink 15 delphi exception

我很恳请您就我在Delphi中遇到的以下问题提出建议try/except.

我有一个简单的应用程序 - 一个命名的MainForm fr_MAIN和一个TDataModule命名的DM.DM是不是自动创建的,但它在运行时创建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;
Run Code Online (Sandbox Code Playgroud)

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

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

问题是当我点击时Button2,我收到'this is error!'异常消息,其余的DM code here没有运行 - 这是正确的!但后来我也收到了'DM started!'消息而不是'DM not started!'消息.

通过DM中断动作引发的异常,但不会在except窗体的块中被捕获!

为什么是这样?

Tom*_*erg 21

TDataModule1对其OnCreate事件中引发的异常进行了特殊处理.

这里处理异常:

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;
Run Code Online (Sandbox Code Playgroud)

默认情况下,TApplication分配TApplication.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;
Run Code Online (Sandbox Code Playgroud)

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

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

Vcl.Forms.TApplication.OnException

使用OnException更改应用程序代码未处理异常时发生的默认行为.在HandleException方法中自动调用OnException事件处理程序.

但这个例外仍然会被抓住并被驳回TDataModule.DoCreate().如果你想避免这种情况,那么异常会在调用堆栈中传播,不要从TDataModule.OnCreate事件中引发异常.重写虚拟TDataModule.Create()构造函数并从那里引发异常.

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