开发者

Delphi. How to know if TEvent is Signaled or not?

please tell me: how to know if TEvent is Signaled or not?

Click on STOP-button = SetEvent(Events[1]);

I am trying to unzip an archive and if STOP-button is pressed then a tread must be terminated and Unzippping must be aborted.

My code:

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;

But if I press STOP-button(SetEvent(Events[1])) nothing happens.

PS: I am using WaitForMultipleObjects(Event[1],Event[2]) in a thread. Event [1] is being used as a signal of STOP in t开发者_如何转开发wo parts: in ZipForge1OverallProgress and WaitForMultipleObjects.


Call WaitForMultipleObjects, but do it properly. You haven't shown that code, and the code you have shown doesn't look right anyway.

First, it looks like you're trying to check whether the Events[1] element is a null pointer. Null pointers in Delphi are spelled nil, not null; the latter is a function that returns a null Variant value (but since Variant is convertible to lots of other types, the compiler probably doesn't alert you that your code is wrong). Next, it looks as though the event you're handling has a Cancel parameter that you can set to notify the caller that it should stop what it's doing, but instead of just setting that, you're throwing an EAbort exception.

If the progress event you show here is really running in a separate thread, then it must not modify property of VCL objects like TProgressBar. You need to use Synchronize to make sure VCL operations only occur in the VCL thread.

As I said, you need to call WaitForMultipleObjects property. That means passing it four parameters, for one thing. You appear to have an array with at least two handles in it, so call it like this:

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;

If all you want to do is check whether the handle is signaled, but you don't want to wait for it to become signaled if it isn't already, then use a timeout value of zero.


'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;
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜