2011-06-06 57 views
1

請告訴我:如何知道TEvent是否有信號?德爾福。如何知道TEvent是否有信號?

點擊STOP按鈕= SetEvent(Events[1]);

我想解壓縮的檔案,如果按了停止鍵則胎面必須終止並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]))沒有任何反應。我在線程中使用WaitForMultipleObjects(Event[1],Event[2])。事件[1]被用作兩個部分的STOP信號:ZipForge1OverallProgressWaitForMultipleObjects

回答

3

請致電WaitForMultipleObjects,但要正確地做。您沒有顯示該代碼,並且您顯示的代碼看起來不正確。

首先,它看起來像你試圖檢查Events[1]元素是否爲空指針。 Delphi中的空指針拼寫爲nil,而不是null;後者是a function that returns a null Variant value(但由於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; 

如果你想要做的是檢查手柄是否發出信號,但你不希望等待如果它已經不成爲信號,則使用超時值爲零。

+0

好點,我認爲處理程序是從同步方法調用的,但可能不是... – 2011-06-06 01:11:03

+0

我的代碼。起初:form2.ZipForge1。提取文件('*。*'); ...然後 對象信號:= WaitForMultipleObjects(2,@ Events,false,INFINITE); if ObjectSignal = WAIT_OBJECT_0 then ...; 事件#2設置了一些東西,我們不在乎。 事件1(停止按鈕):如果在解壓縮WaitForMultipleObjects之後按下停止按鈕(SetEvent#1)將作出反應。但是如果我在解壓縮的時候按Stop-Button? ZipForge必須知道我按下了按鈕,必須中止並且必須完成Thread.Terminate。他們傷心,如果我會使用布爾值來檢查它而不是事件,那麼布爾值可能是錯誤的,值可以是現金,所以我使用TEvent。 – Michael 2011-06-06 02:03:56

+1

「他們」正在討論使用布爾值來檢查是否按下了「停止」按鈕,而不是使用布爾值來停止進一步處理zip文件。 「他們」已經明確地*給出*一個布爾變量供您填寫('Cancel'參數)。你應該修改它,如文件肯定告訴你。你不需要拋出異常。不要等待無限的事件被髮信號 - 這是適得其反的,因爲你正在阻止zip文件被進一步處理。 – 2011-06-06 04:14:05

1

'if Events [1] <> null then begin'是這個僞代碼嗎?不喜歡它 - 看起來更像真正的德爾福給我:)如果是這樣,你只是檢查是否分配了事件對象,而不是信號。

如果你想在你的OverallProgress處理輪詢停止事件,你需要調用WaitForSingleObject()與0

超時你能不能只檢查一個「停止」布爾在你的處理器?這比內核調用要快得多。您可能還需要該事件,以便在需要中止/終止時,線程頂部的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; 
+0

我的代碼。起初:form2.ZipForge1.ExtractFiles('。'); ...然後ObjectSignal:= WaitForMultipleObjects(2,@ Events,false,INFINITE);如果ObjectSignal = WAIT_OBJECT_0則...;事件#2設置了一些東西,我們不在乎。事件#1(停止 - 按鈕):如果在解壓縮WaitForMultipleObjects之後按下停止按鈕(SetEvent#1)將作出反應。但是如果我在解壓縮的時候按Stop-Button? ZipForge必須知道我按下了按鈕,必須中止並且必須完成Thread.Terminate。他們傷心,如果我會使用布爾值來檢查它而不是事件,那麼布爾值可能是錯誤的,值可以是現金,所以我使用TEvent。 – Michael 2011-06-06 02:21:37

+0

@邁克爾:如果你想提供更多的信息(如添加一些代碼示例),你可以編輯你的問題。在註釋中,可以通過用反引號(\')字符來使代碼更易讀。 – 2011-06-06 07:05:17