我正在尝试以下代码。但是,如果在此代码运行时单击窗体的关闭按钮,则不会发生任何操作。我怎么能纠正这个?即使执行此循环,我也需要关闭表单。
procedure TForm1.Button1Click(Sender: TObject);
var
i: Integer;
begin
for i := 0 to 9999999 do
begin
Memo1.Lines.Add('hi');
Application.ProcessMessages;
end;
end;
答案 0 :(得分: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;
我认为这不是CLR程序,所以此时唯一发生的事情就是在FTerminate := True
上设置Application
。这反映在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;
另外,请注意首先使用Application.ProcessMessages
,因为它将处理应用程序的所有消息。有关可能出现的问题的简单概念,请尝试将IntToStr(i)
而不是'hi'
添加到Memo1.Lines
,从柜台上敲几个数量级,然后点击两三个按钮快速连续几次看输出......
答案 1 :(得分:6)
检查申请已终止:
for i := 0 to 9999999 do
begin
Memo1.Lines.Add('hi');
Application.ProcessMessages;
if Application.Terminated then Exit;
end;
答案 2 :(得分:1)
您需要在线程中运行任何紧密循环。这将解决问题。
但是如果你想保持代码原样,Application.ProcessMessages将使你的循环非常慢。所以你需要不经常运行Application.ProcessMessages:
Counter:= 0;
for i := 0 to 9999999 do
begin
DoSomeStuff;
{ Prevent freeze }
inc(Counter);
if counter > 10000 then
begin
Counter:= 0;
Application.ProcessMessages;
if Application.Terminated then Exit;
end;
end;