请告诉我:如何知道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信号:ZipForge1OverallProgress
和WaitForMultipleObjects
。
答案 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;