当在Delphi中运行一个巨大的for循环时,为什么'form close'事件没有发生?

jim*_*web 1 delphi performance pascal delphi-xe2

我正在尝试下面的代码.但是,如果在此代码运行时单击窗体的关闭按钮,则不会发生任何操作.我怎么能纠正这个?即使执行此循环,我也需要关闭表单.

procedure TForm1.Button1Click(Sender: TObject);
var
  i: Integer;
begin
  for i := 0 to 9999999 do
  begin
    Memo1.Lines.Add('hi');
    Application.ProcessMessages;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

Mas*_*ler 13

看看里面发生了什么Application.ProcessMessages.

当您关闭主窗体时,Windows会向WM_QUIT程序发送一条消息.相关部分TApplication.ProcessMessages看起来像这样:

    if Msg.Message <> WM_QUIT then
    begin
      //skipped
    end
    else
    begin
{$IF DEFINED(CLR)}
      if Assigned(FOnShutDown) then FOnShutDown(self);
      DoneApplication;
{$IFEND}
      FTerminate := True;
    end;
Run Code Online (Sandbox Code Playgroud)

我想这是不是一个CLR程序,所以出现这种情况在这一点的唯一事情是设置FTerminate := TrueApplication.这反映在Application.Terminated酒店.

当应用程序关闭时,为了安全关闭它所做的一件事就是等待所有线程完成.这个代码恰好在主线程中运行,但原则在任何线程中都是相同的:如果你正在做一个可能需要提前完成的长时间运行的任务,你必须明确检查提前终止.

知道了这一点,很容易弄清楚如何修复代码:

procedure TForm1.Button1Click(Sender: TObject);
var
  i: Integer;
begin
  for i := 0 to 9999999 do
  begin
    Memo1.Lines.Add('hi');
    Application.ProcessMessages;
    if Application.Terminated then
      Break;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

另外,请注意Application.ProcessMessages首先使用,因为它将处理应用程序的所有消息.对于什么可能出错一个简单的想法,尝试加入IntToStr(i)的,而不是'hi'Memo1.Lines,磕了几个量级关闭计数器的订单,然后按一下按钮两次或三次快速连续并观察输出...

  • @jimsweb,参见[`Delphi应用程序中Application.ProcessMessages的黑暗面](http://delphi.about.com/od/objectpascalide/a/delphi-processmessages-dark-side.htm).每次您认为需要时,都应该重新考虑实施策略. (17认同)
  • 您的意思是说,使用'Application.ProcessMessages'并不好? (2认同)

Uwe*_*abe 6

检查Apllication终止:

  for i := 0 to 9999999 do
  begin
    Memo1.Lines.Add('hi');
    Application.ProcessMessages;
    if Application.Terminated then Exit;
  end;
Run Code Online (Sandbox Code Playgroud)

  • @Arioch'The,对于ButtonClick?此外,Abort会为进程设置错误条件.我会认为Abort有点过分了. (2认同)