1

教えてください: TEvent が Signaled かどうかを知る方法は?

STOPボタンをクリック=SetEvent(Events[1]);

アーカイブを解凍しようとしていますが、STOP ボタンが押された場合、トレッドを終了し、解凍を中止する必要があります。

私のコード:

procedure TForm2.ZipForge1OverallProgress(Sender: TObject; Progress: Double;
  Operation: TZFProcessOperation; ProgressPhase: TZFProgressPhase;
  var Cancel: Boolean);
begin
  if Events[1]<>null then
  begin
    ThreadUpdating.Terminate;
    Abort;
  end else
    form2.Update_ProgressBar.Position := Trunc(Progress);
end;

しかし、STOP-button(SetEvent(Events[1])) を押しても何も起こりません。

PS:WaitForMultipleObjects(Event[1],Event[2])スレッドで使用しています。イベント [1] は と の 2 つの部分で STOP の信号として使用されていZipForge1OverallProgressますWaitForMultipleObjects

4

2 に答える 2

3

を呼び出しWaitForMultipleObjectsますが、適切に実行します。あなたはそのコードを示していません、そしてあなたが示したコードはとにかく正しく見えません。

Events[1]まず、要素がnullポインタであるかどうかを確認しようとしているようです。Delphiのnullポインタは、 ;nilではなくスペルです。null後者はnull値を返す関数Variantです(ただし、Variantは他の多くのタイプに変換できるため、コンパイラーはコードが間違っていることを警告しない可能性があります)。次に、処理しているイベントに、実行中の処理を停止する必要があることを呼び出し元に通知するように設定できるパラメーターがあるように見えますが、それを設定するだけでなく、例外Cancelをスローしています。EAbort

ここに表示する進行状況イベントが実際に別のスレッドで実行されている場合は、のようなVCLオブジェクトのプロパティを変更してはなりませんTProgressBarSynchronizeVCL操作がVCLスレッドでのみ発生することを確認するためにを使用する必要があります。

私が言ったように、あなたは財産を呼ぶ必要がありWaitForMultipleObjectsます。つまり、1つには、4つのパラメーターを渡すことを意味します。少なくとも2つのハンドルを持つ配列があるように見えるので、次のように呼び出します。

var
  Ret: DWord;

Ret := WaitForMultipleObjects(2, @Events[1], False, Timeout);
case Ret of
  Wait_Object_0: begin
    // Events[1] is signaled
  end;
  Wait_Object_0 + 1: begin
    // Events[2] is signaled
  end;
  Wait_Timeout: begin
    // Neither is signaled. Do some more work, or go back to waiting.
  end;
  Wait_Failed: begin
    RaiseLastOSError;
  end;
end;

ハンドルが通知されているかどうかを確認するだけで、まだ通知されていない場合は通知されるのを待ちたくない場合は、タイムアウト値ゼロを使用します。

于 2011-06-06T00:57:24.143 に答える
1

'if Events [1] <> null then begin'はこの擬似コードですか?気に入らない-私には本物のDelphiのように見える:)もしそうなら、あなたはイベントオブジェクトが割り当てられているかどうかを確認するだけであり、通知されるのではありません。

オーバーオールプログレスハンドラーで停止イベントをポーリングする場合は、タイムアウト0でWaitForSingleObject()を呼び出す必要があります。

ハンドラーで「停止」ブール値をチェックするだけではいけませんか?これは、カーネル呼び出しよりもはるかに高速です。アボート/終了が必要なときにスレッドの先頭でWFMO呼び出しが通知されるように、または常に停止をチェックすることでWFMO配列内の他のイベントの通知を回避できるように、イベントも必要になる場合があります。

TmyThread = class(TThread)
..
public
  stopRequested:boolean;
  procedure stop;
  ..
end;

procedure TmyThread.stop;
begin
  stopRequested:=true;
  someEventInWFMOarray.signal;
end;

procedure TmyThread.execute;
begin;
  while true do
  begin
    waitForMultipeObjects();
    if stopRequested then exit;
    work;
  end;
end;

TForm2.ZipForge1OverallProgress(sender:TObject,......)
begin
  cancel:=TmyThread(Sender).stopRequested;
  if cancel then exit;
  doStuff; 
end;
于 2011-06-06T01:07:12.187 に答える