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;
精彩评论