1

次のコードを試しています。ただし、このコードの実行中にフォームの閉じるボタンをクリックしても、何も起こりません。どうすればこれを修正できますか? このループが実行されているときでも、フォームを閉じる必要があります。

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

3 に答える 3

14

内部で何が起こっているか見てみましょうApplication.ProcessMessages

メイン フォームを閉じると、WindowsWM_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 := Trueon に設定することだけですApplication。これは、プロパティに反映されApplication.Terminatedます。

アプリケーションがシャットダウンするとき、安全にシャットダウンするために行うことの 1 つは、すべてのスレッドが終了するのを待つことです。このコードはたまたまメイン スレッドで実行されていますが、原則はどのスレッドでも同じです。早期に終了する必要がある可能性のある長時間実行されるタスクを実行している場合は、早期終了を明示的に確認する必要があります。

これを知っていれば、コードを修正する方法を簡単に理解できます。

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。カウンターから 2 ~ 3 桁ノックアウトしてから、ボタンを 2 ~ 3 回すばやく連続してクリックし、出力を確認してください。

于 2013-06-04T16:29:31.123 に答える
6

終了したアプリケーションの確認:

  for i := 0 to 9999999 do
  begin
    Memo1.Lines.Add('hi');
    Application.ProcessMessages;
    if Application.Terminated then Exit;
  end;
于 2013-06-04T16:26:30.043 に答える
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;
于 2015-08-27T11:58:09.413 に答える