5

私が取り組んでいる単純なDelphiプログラムがあります。このプログラムでは、スレッドを使用してプログラムの機能をGUIから分離し、より長いタスクなどでGUIの応答性を維持しようとしています。 「コントローラー」TThread、および「ビュー」TForm。ビューは、を介してコントローラーメッセージを送信するために使用するコントローラーのハンドルを認識していますPostThreadMessage。これまで、この種のモデルをメインフォームではないフォームに使用しても問題はありませんでしたが、何らかの理由で、このモデルをメインフォームに使用しようとすると、スレッドのメッセージループが終了します。

スレッドメッセージループのコードは次のとおりです。

procedure TController.Execute;
var
  Msg : TMsg;
begin
  while not Terminated do begin
    if (Integer(GetMessage(Msg, hwnd(0), 0, 0)) = -1) then begin
      Synchronize(Terminate);
    end;

    TranslateMessage(Msg);
    DispatchMessage(Msg);

    case Msg.message of
      // ...call different methods based on message
    end;
  end;
end;

コントローラを設定するには、次のようにします。

Controller := TController.Create(true); // Create suspended
Controller.FreeOnTerminate := True;
Controller.Resume;

メインフォームのメッセージを処理するために、次のループと次のループの両方を使用してみApplication.Runました(直後Controller.Resume

while not Application.Terminated do begin
  Application.ProcessMessages;
end;

私はここで立ち往生しています-どんな助けでも大歓迎です。

4

2 に答える 2

3

私はあなたのコードを基本的にそのままテストしました、そしてそれはうまくいきました。GetMessageが-1を返した後、GetLastErrorの呼び出しを追加して、問題が何であるかを確認してください。

コントローラースレッド内にウィンドウを作成しているかどうかはコードから完全にはわかりませんが、そうでない場合は、GetMessageのHWNDとして0ではなく-1を渡し、TranslateMessage/DispatchMessage呼び出しを削除することをお勧めします。それらに続くものは、受信するすべてのメッセージを処理する必要があります。

また、エラー時に「同期(終了)」を行う必要はありません。Terminateは、「Terminated」ブール値をtrueに設定するだけなので、同期する必要はありません。「Break」を使用して、同じ効果でループから抜け出すことも簡単にできます。

于 2010-03-22T21:37:19.620 に答える
0

whileループの「終わり」はどこにありますか?私はあなたが行方不明で終わりだと思います。したがって、おそらく(実際のコードによっては)、while not Terminated do1つのステートメントで際限なくループに陥っています。

于 2010-03-22T21:00:31.943 に答える