【问题标题】:How to handle EAccessViolation when closing a Form关闭表单时如何处理 EAccessViolation
【发布时间】:2016-04-08 21:32:14
【问题描述】:

当我关闭应用程序的表单时出现 EAccessViolation,我不知道如何处理,我有两个单元,这里是主要单元相关代码:

unit MainUnit;
uses
  .., myComponent1;

implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
  MyComponent1.doSomeWork(p1, p2, ..., pn);
end;
procedure TForm1.OnMyComponen1tEvent(sender: TObject; p: Integer);
begin
  memo1.Lines.Add(message);
end;
end.

这个单元使用的另一个单元是一个组件类,我在其中向 memo1 发送一个信号来显示消息,当然使用组件事件,它是这样的:

unit myComponent;
type
TMyComponentEvent = procedure(sender: TObject; p: integer) of object;
type
TMyComponent = class(TComponent)
// Properties and events declaration
procedure TPThread.Execute;
begin
  try
    // Create and run some worker threads
    // Wait for them to finish the job
    // This is the last thing to do:
    if Assigned(FOnMyComponentEvent) then
    begin
      FOnMyComponentEvent(Self, p);
    end;
 finally
  //free ressources
end;
end;

procedure TMyComponent.DoSomeWork;
begin
  TPThread.Create(p1, p2 ...);
end;
end.

当我在程序完成其工作(线程仍在工作)之前关闭表单时,我得到了那个异常,但有时,没有引发异常。好吧,当引发异常时,它表示该行:memo1.Lines.Add(message);。 我不知道如何解决它,那么如何防止异常发生?

【问题讨论】:

  • 在对象被销毁后不要访问它们。如果您需要有关如何实现这一目标的帮助,我们希望看到一些代码。

标签: delphi exception-handling delphi-2010


【解决方案1】:

听起来您在销毁表单时没有将MyEvent 事件设置为零,例如

procedure TForm1.FormCreate(sender: TObject);
begin
  OtherUnit.MyEvent := MyEvent;
end;

procedure TForm1.FormDestroy(sender: TObject);
begin
  OtherUnit.MyEvent := nil;
end;

【讨论】:

  • 我想我没有提到一个重要的事情是:另一个单元是一个组件,MyEvent是组件事件,它有参数,我尽量不要让我的问题复杂化,否则我'将编辑我的问题并发布相关代码。
  • @Safa:然后编辑您的问题并将高度相关的信息添加到您的问题中,而不是埋在对答案的评论中。您需要发布一个完整的 minimal reproducible example 来证明该问题,而不是您发布的完全没有上下文的小 sn-p。
  • @Safa:如果组件在 Form 上,则无需重置事件,因为组件将在 Form 被释放时被释放。如果组件是在其他地方创建的,并且表单是动态分配给事件的,那么我上面的回答仍然适用,只需将 OtherUnit 替换为组件指针即可。
  • 这种情况变得更糟了。您的组件正在创建一个工作线程,然后在该线程的上下文中触发事件。偶数处理程序试图从主 UI 线程外部访问 UI 控件。你不能这样做,这很容易导致访问冲突(在其他错误的孩子中)。在 UI 线程之外访问 UI 控件是不安全的!因此,要么 1) 工作线程必须使用 TThread.Synchronize() 或其他线程同步机制来触发 UI 线程中的事件,要么 2) 事件处理程序本身必须相应地委托给 UI 线程。
  • 而且你仍然有一个问题,如果在组件线程运行时关闭并释放了表单,你仍然需要取消分配事件处理程序,这样线程就不会再调用它了。否则,Form 需要在 Form 关闭之前告诉组件停止线程。
猜你喜欢
  • 1970-01-01
  • 2011-08-28
  • 1970-01-01
  • 1970-01-01
  • 2013-02-17
  • 1970-01-01
  • 2021-08-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多