德尔福。如何知道TEvent是否有信号?

时间:2011-06-06 00:33:59

标签: delphi events signals terminate

请告诉我:如何知道TEvent是否有信号?

点击STOP-button = SetEvent(Events[1]);

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

我的代码:

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按钮(SetEvent(事件[1]))则没有任何反应。

PS:我在一个帖子中使用WaitForMultipleObjects(Event[1],Event[2])。事件[1]被用作两个部分的STOP信号:ZipForge1OverallProgressWaitForMultipleObjects

2 个答案:

答案 0 :(得分:3)

致电WaitForMultipleObjects,但要正确行事。您没有显示该代码,并且您显示的代码无论如何都看起来不正确。

首先,看起来您正在尝试检查Events[1]元素是否为空指针。 Delphi中的空指针拼写为nil,而不是null;后者是a function that returns a null Variant value(但由于Variant可以转换为许多其他类型,编译器可能不会提醒您代码是错误的)。接下来,看起来您正在处理的事件有一个Cancel参数,您可以将其设置为通知调用者它应该停止它正在做的事情,但是不是只设置它,而是抛出{{ 3}}例外。

如果您在此处显示的progress事件确实在单独的线程中运行,则它不能修改TProgressBar等VCL对象的属性。您需要使用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;

如果您要做的只是检查是否已发出信号,但您不希望等待,如果它尚未发出信号,然后使用超时值零。

答案 1 :(得分:1)

'如果事件[1]&lt;&gt; null然后开始'是这个伪代码?不喜欢它 - 对我来说看起来更像真正的Delphi :)如果是这样,你只是检查是否分配了Event对象,而不是发出信号。

如果要在OverallProgress处理程序中轮询停止事件,则需要以超时0调用WaitForSingleObject()。

你能不能只检查处理程序中的'stop'布尔值?这比内核调用要快得多。您可能还需要事件,以便在需要中止/终止时,线程顶部的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;