1

TThread の子孫とオブジェクトのリストがあり、それぞれにそのようなスレッドの独自のコピーがあり、CreateEvent() API で作成された Event オブジェクトがあります。

異なるオブジェクトは、イベントの発火によって相互に作用します。つまり、各スレッドは、他のスレッドがそのイベントを発生させるまで待機する必要があります。もちろん、永続的に機能する「マスター」スレッドが 1 つあるため、セルフブロッキングは発生しません。このシステムは、各オブジェクトの Execute メソッドの最後まで問題なく機能します。

アプリを閉じるなどして、すべてのスレッドを中断しようとすると、probkem が表示されます。この場合、各スレッドの Terminate メソッドを呼び出す外部関数が必要です。

  for i := 0 to FLayers.Count - 1 do
  begin
    FLayers.Layer[i].FTerminating := true;
    f := true;
    while f do
    begin
      f := FLayers.Layer[i].IsActive;
      if f then
      begin
        Sleep(100);
        Application.ProcessMessages;
      end;
    end;
    FLayers.Layer[i].FTerminating := false;
  end;

この関数は Form.OnClose() イベントにあります。

問題は、約 2 つのスレッドが正常に終了することですが、他のすべては WaitForSingleObject() 呼び出しで停止します。

procedure TLayerThread.Execute;
begin
FLayer.FIsActive := true;
...............
repeat
 //
 if Terminated or
   FLayer.FTerminating or
   (FLayer.FEvent = INVALID_HANDLE_VALUE) then
   begin
     break;
   end;
 //
 Fres := WaitForSingleObject(FLayer.FEvent, 100); <<<<<<<<<<<<<<<<<<<<<<<<
until Fres <> WAIT_TIMEOUT;
...........
FLayer.FIsActive := false;
end;

すべてのスレッドがその行で停止(ハング) します。タイムアウト値が設定されているにもかかわらず、上記でマークされています。

何か案は?

Delphi 7 と Win XP を使用しています。

前もって感謝します。

ファローアップ -

この問題は、Execute() メソッド内からの Synchronize() 呼び出しでカバーされていることがわかりました。ここで何が悪いのか理解できません。Synchronize() は、ビジュアル コントロールの更新などの通常のことを呼び出しますが、それ以上は何もしません。

デバッガーが示すように、一部のスレッドが WaitForSingleObject() 呼び出しでハングしていますが、これは異なるスレッドを調整するために Execute() メソッドで使用するものではなく、別の呼び出しです。私はそれがここにあると推測できます:

class procedure TThread.Synchronize(ASyncRec: PSynchronizeRecord);
.................
        LeaveCriticalSection(ThreadLock);
        try
          WaitForSingleObject(SyncProc.Signal, INFINITE);<<<<<<<<<<<<<<<<<<<<<<
        finally
          EnterCriticalSection(ThreadLock);
        end;
..................

私のコードのどこが間違っているのか教えてくれる人はいますか? Execute() メソッド内から Synchronize() を呼び出すことが許可されていないとは聞いたことがありません...

4

1 に答える 1

1

WaitForSingleObjectの代わりに、WaitForMultipleObjectsを無限のタイムアウトで使用し、FLayer.FEvent と 2 番目の終了イベントの 2 つのイベントを待機する必要があります。

AFAIR は、プロセスごとに 1 つの終了イベントを作成する必要があります。WaitForMultipleObjects が終了イベントの ID を返す場合、ループを終了します。

OnClose() メソッドでは、単純にすべての終了イベントを通知する必要があります。

于 2010-12-17T20:44:31.017 に答える