13

メイン VCL スレッドへのアクセスをシリアル化するために同期を使用して Delphi コードを作成したが、このコードを非 VCL アプリケーションで使用した場合、アプリケーションのメイン スレッドと同期するのでしょうか、それともまったく効果がないのでしょうか。


例:

procedure TMyThread.Execute;
begin

  // ... other code

  Synchronize(SomeMethod);

  // ...

end;

仮定しましょう

  • エンドレス ループで (または終了するまで) 実行されるメイン スレッドを持つ非 VCL アプリケーションです。
  • CheckSynchronizeメイン スレッドが直接または WakeMainThread ハンドラーで呼び出されない
  • セカンダリ スレッドが実行され、上記の例のように Synchronize(SomeMethod) が実行されます

スレッドは Synchronize(SomeMethod) 行でハングしますか?

4

3 に答える 3

9

TThread非 VCL プログラムが同期キューをチェックする機能を提供するため、メソッドの同期を期待するマルチスレッド ライブラリを引き続き使用できます。これについては、 のドキュメントでCheckSynchronize説明されています。キューをチェックするのはアプリケーションの仕事であり、ライブラリの仕事ではないことに注意してください。

アプリケーションがコントラクトの一部を尊重している限り、 を使用してSynchronizeも問題ありません。そうでない場合、プログラムは正しく動作しませんが、正確にどのような症状が予想されるかはわかりません。ぶら下げは確かにもっともらしく聞こえます。

于 2012-05-21T16:48:01.307 に答える
6

非 VCL アプリケーションで同期を使用するのは危険ですか?

はい、危険です。メインスレッドが呼び出していない場合CheckSynchronizeSynchronizeデッドロックが発生します。

仮定しましょう

  • エンドレス ループで (または終了するまで) 実行されるメイン スレッドを持つ非 VCL アプリケーションです。
  • CheckSynchronizeメインスレッドが直接またはWakeMainThreadハンドラーで呼び出されない
  • セカンダリ スレッドが実行Synchronize(SomeMethod)され、上記の例のように実行されます

糸は糸に掛かるSynchronize(SomeMethod)でしょうか?

への呼び出しSynchronizeは、メイン スレッドが を呼び出すまでバックグラウンド スレッドをブロックしますCheckSynchronize。そのため、メイン スレッドが を呼び出さない場合CheckSynchronize、バックグラウンド スレッドは無期限にブロックされます。

次のプログラムはこれを示しています。

program TheBigSleep;

{$APPTYPE CONSOLE}

uses
  SysUtils, Classes, Windows;

type
  TMyThread = class(TThread)
  protected
    procedure Execute; override;
  end;

procedure TMyThread.Execute;
begin
  Synchronize(SysUtils.Beep);
end;

begin
  with TMyThread.Create do
    WaitForSingleObject(Handle, INFINITE);
    //don't call WaitFor since that, in turn, calls CheckSynchronize
end.
于 2012-05-21T17:51:41.157 に答える
1

他のアプリが使用できるように Delphi コードをライブラリに入れているので、Synchronize()スレッドにはそれ自体の外側で何が起こっているのかという概念がないため、使用することはまったくお勧めしません。より良い選択は、必要に応じてスレッドが独自のコンテキストで呼び出すことができるコールバック イベントをスレッドに公開させ、必要に応じてアプリのメイン スレッドと同期するための最適な方法を決定するコールバック関数ハンドラーをアプリに提供させることです。

于 2012-05-22T17:39:02.743 に答える