Delphi 如何捕获TDataModule.OnCreate事件中的异常?
我在Delphi中遇到了一个Delphi 如何捕获TDataModule.OnCreate事件中的异常?,delphi,exception,Delphi,Exception,我在Delphi中遇到了一个try/except块的以下问题 我有一个简单的应用程序——一个名为fr\u MAIN的主窗体和一个名为DM的TDataModule的主窗体DM不是自动创建的,而是在运行时在fr\u MAIN的按钮2中创建的。OnClick事件: procedure Tfr_MAIN.Button2Click(Sender: TObject); begin try DM := TDM.Create(nil); Showmessage('DM started!');
try/except
块的以下问题
我有一个简单的应用程序——一个名为fr\u MAIN
的主窗体和一个名为DM
的TDataModule
的主窗体DM
不是自动创建的,而是在运行时在fr\u MAIN
的按钮2中创建的。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;
procedure TDM.DataModuleCreate(Sender: TObject);
begin
raise Exception.Create('this is error!');
// DM code here ...
end;
DM
在其OnCreate
事件中有一些代码:
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;
procedure TDM.DataModuleCreate(Sender: TObject);
begin
raise Exception.Create('this is error!');
// DM code here ...
end;
问题是,当我点击按钮2
时,我收到“这是错误!”代码>异常消息,此处的DM代码的其余部分不运行-这是正确的!但随后我也收到了“DM start!”代码>消息,而不是'DM not started!'代码>消息
由DM
引发的异常会中断操作,但不会在表单的块中捕获,除非块
这是为什么?TDataModule
1对其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;
因此,TDataModule.DoCreate()
正在捕获异常并将其传递给TApplication.HandleException()
,然后默认情况下会显示一个弹出对话框。由于TDataModule.HandleCreateException()
然后返回True,因此捕获的异常不会重新引发。异常现在被认为已处理,允许程序正常继续执行其Showmessage('DM start!')代码>呼叫
要避免引发异常时出现弹出对话框,可以指定TApplication.OnException
事件处理程序:
Vcl.Forms.TApplication.OneException
使用OneException可更改
应用程序代码不处理异常。OneException事件
HandleException方法中会自动调用处理程序
但是异常仍然会被TDataModule.DoCreate()
捕获并排除。如果要避免这种情况,因此异常会向上传播到调用堆栈,则根本不要从TDataModule.OnCreate
事件引发异常。重写虚拟TDataModule.Create()
构造函数,并从那里引发异常
1:同样的事情也发生在TCustomForm
中,更好的解决方案是对所有表单进行修复
将Forms.pas
从\Vcl\Source文件夹复制到项目文件夹中(或复制到公共共享库文件夹中,以便所有项目都能从中受益)
然后将TCustomForm.HandleCreateException更改为:
function TCustomForm.HandleCreateException: Boolean;
begin
{
If an exception is raised during a form's OnCreate event, the exception is hidden.
This leaves you with an only partially initialized form.
The correct behavior is to **not** eat the exception.
We do that by returning False. The caller will then throw.
}
// Application.HandleException(Self);
// Result := True;
Result := False;
end;
如果您使用的是Delphi的早期版本,则没有HandleCreateException。您必须直接修复呼叫者:
procedure TCustomForm.DoCreate;
begin
{
If the Form.OnCreate event throws an exception, the exception is eaten, and the caller never knows about it.
Don't do that.
}
if Assigned(FOnCreate) then
begin
//try
FOnCreate(Self);
//except
// Just let it throw. Christ you guys are dense.
//Application.HandleException(Self);
//end;
end;
if fsVisible in FFormState then
Visible := True;
end;
默认情况下,TApplication
告诉TDataModule
接受由TDataModule.OnCreate
事件引发的异常(有关具体细节,请参阅Tom的回答)。要执行您要求的操作,您应该重写虚拟的TDataModule.Create()
构造函数来引发异常,而不是使用TDataModule.OnCreate
事件。非常感谢亲爱的Lebeau先生和Brunberg先生!这次我学到了一些非常重要的东西,关于TDataModule创建事件的进展情况。为了更清楚地了解这一点,在不久的将来,DM将从TService中创建(并发布)——这对我来说会使事情更加复杂。我知道你提出的想法,但凭借我在德尔福的技能,我现在不想再去想它了——至少在我建立TService之前是这样的——目前我将通过一个事实来了解,除了加薪例外。在DM内部创建。从另一个单位创建非常感谢你,致以最良好的问候