1

请告诉我:如何知道 TEvent 是否已发出信号?

单击停止按钮 =SetEvent(Events[1]);

我正在尝试解压缩档案,如果按下停止按钮,则必须终止踏板并且必须中止解压缩。

我的代码:

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] 分两部分用作 STOP 信号:inZipForge1OverallProgressWaitForMultipleObjects

4

2 回答 2

3

打电话WaitForMultipleObjects,但要正确地做。您还没有显示该代码,并且您显示的代码看起来也不正确。

首先,您似乎正在尝试检查Events[1]元素是否为空指针。Delphi 中的空指针是拼写的nil,不是null;后者是一个返回空值的函数Variant(但由于Variant可以转换为许多其他类型,编译器可能不会提醒您代码错误)。接下来,您正在处理的事件看起来好像有一个Cancel参数,您可以设置该参数以通知调用者它应该停止正在执行的操作,但不是仅仅设置它,而是抛出EAbort异常。

如果您在此处显示的进度事件确实在单独的线程中运行,则它不得修改 VCL 对象的属性,例如TProgressBar. 您需要使用Synchronize来确保 VCL 操作只发生在 VCL 线程中。

正如我所说,您需要调用WaitForMultipleObjects属性。这意味着向它传递四个参数,一方面。您似乎有一个数组,其中至少有两个句柄,所以这样称呼它:

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' is this pseudocode? Doesn't lok like it - looks more like real Delphi to me:) If so, you are just checking to see if the Event object is assigned, rather than signaled.

If you want to poll the stop event in your OverallProgress handler, you need to call WaitForSingleObject() with a timeout of 0.

Can you not just check a 'stop' boolean in your handler? This would be much quicker than a kernel call. You may need the Event as well so that the WFMO call at the top of the thread gets signaled when an abort/terminate is needed or you might get away with signaling some other event in the WFMO array by always checking for stop:

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 回答