2016-11-17 34 views
4

,我們可以調用同一個線程在幾個時間MyThread.waitfor。如果線程已經終止沒有問題,這將不會引發任何異常並立即返回(正常行爲)。這是Android下TThread的bug嗎?在Windows

在Android上,這是不同的,如果我們調用兩次MyThread.waitfor那麼我們將有第二次嘗試用「沒有這樣的過程」異常。

function TThread.WaitFor: LongWord; 
{$ELSEIF Defined(POSIX)} 
var 
    X: Pointer; 
    ID: pthread_t; 
begin 
    if FExternalThread then 
    raise EThread.CreateRes(@SThreadExternalWait); 
    ID := pthread_t(FThreadID); 
    if CurrentThread.ThreadID = MainThreadID then 
    while not FFinished do 
     CheckSynchronize(1000); 
    FThreadID := 0; 
    X := @Result; 
    CheckThreadError(pthread_join(ID, X)); 
end; 
{$ENDIF POSIX} 

錯誤是由因爲調用WAITFOR他們設置FThreadID:= 0,關閉過程的任何進一步的通話將failled

我覺得這是必須這樣寫:

function TThread.WaitFor: LongWord; 
{$ELSEIF Defined(POSIX)} 
begin 
    if FThreadID = 0 then exit; 
    ... 
end; 
{$ENDIF POSIX} 

什麼你認爲 ?我需要在emb上打開一個bug請求嗎?

回答

5

pthread_join文檔說:

與先前已未定義行爲的聯合結果線程加入。

這解釋了爲什麼TThread採取措施避免調用未定義的行爲。

有缺陷的設計?這是有爭議的。如果我們要考慮這個課程的設計,讓我們像設計師一樣擴大討論範圍。 Windows線程可以由多個不同的線程等待。 pthreads不是這種情況。鏈接的文檔也說:

如果多個線程同時嘗試用同一線程的加入,結果是不確定的。

所以我不認爲Embarcadero可以合理地在Posix平臺上實現與Windows上已經存在的相同的行爲。正如你所描述的那樣,他們肯定會從同一個線程中重複等待。那麼,他們必須堅持線程返回值,以便WaitFor可以返回它。但那隻會讓你在那裏分手,反正也不會很有用。畢竟,你爲什麼會再次從同一個線程中等待呢?

我懷疑FThreadID設置爲0,以避免未定義的行爲並以更穩健的方式失敗。但是,如果多個線程調用WaitFor然後有一個數據競爭如此不確定的行爲仍然是可能的。

如果我們想成爲慈善然後我們就可以

離開這些具體細節一側,很顯然,如果WaitFor通過調用pthread_join然後跨平臺的不同行爲實現是必然的。 Embarcadero公司試圖對準TThread實現各個平臺,但由於平臺的功能不同,它們不能完全等同。 Windows提供了比pthread更豐富的線程原語。

如果英巴卡迪諾選擇了不同的路徑,他們可以完美地對齊平臺,但需要在Posix上更加努力。它可以複製Windows的行爲存在,但這種特殊的方法將不得不比其他pthread_join東西來實現。我想你將不得不適應pthreads的不同功能。在pthread中,僅僅爲了方便起見,包含等待線程的能力。如果您確實想要支持重複等待,您最好等待事件或條件變量。另一方面,您可能只是重新創建您的代碼,以確保您只需等待一次。

所以,總而言之,如果還沒有人,你應該提出一個Embarcadero的問題。他們可能會考慮支持你的方案。在系統中有一個問題是值得的。但是,如果他們選擇不做任何事情並且證明這一點,那麼不要感到驚訝,因爲無法克服更廣泛的平臺差異,並且班級需要額外的複雜性來支持您的毫無意義的用例。有一點我希望我們都可以同意,但是TThread.WaitFor的Delphi文檔應該涵蓋這些問題。

+0

感謝大衛,但如果你看waitfor的實現,他們設置FThreadID:= 0,所以任何進一步調用waitfor可以檢查FThreadID = 0,如果是立即返回? – loki

+0

他們可以這樣做,我想。但是他們不能有多個等待的線程。無論如何,你爲什麼要從同一個線程中等待兩次? –

+0

它不是真的關於多線程,但多功能..例如,當你有幾個功能(這是所有從主線程調用),需要等待線程完成之前繼續(這些功能都是獨立的)。那麼所有的測試MyThread.waitfor。當然,我可以更新所有的功能,如果不是MyThread.checkTerminated然後MyThread.waitfor – loki