2011-06-16 64 views
6

是否有可能從線程調用CopyFileEx和CopyCallback/ProgressRoutine函數(ProgressBar.Position將被同步)?CopyFileEx可以從輔助線程調用嗎?

我可以在線程中聲明CopyCallback/ProgressRoutine函數嗎?我在@ProgressRoutine的CopyFileEx中得到錯誤:「需要變量」。

回答

12

當然這是可能的。回調函數將在調用CopyFileEx的線程的上下文中調用。如果您需要同步某些UI命令,請使用Delphi通常的TThread.Synchronize或其他任何您想要的線程間同步技術。

回調函數不能是線程類的方法。它需要匹配由API規定的簽名,因此它需要是獨立的功能。當你聲明它正確時,當你將它傳遞給CopyFileEx時,你不需要使用@運算符。

function CopyProgressRoutine(TotalFileSize, TotalBytesTransferred: Int64; 
    StreamSize, StreamBytesTransferred: Int64; 
    dwStreamNumber, dwCallbackReason: DWord; 
    hSourceFile, hDestinationFile: THandle; 
    lpData: Pointer): DWord; stdcall; 

,您可以給回調函數訪問相關的線程對象與lpData參數。傳遞給線程對象的引用爲參數,當你調用CopyFileEx

procedure TCopyThread.Execute; 
begin 
    ... 
    CopyResult := CopyFileEx(CurrentName, NewName, CopyProgressRoutine, Self, 
    @Cancel, CopyFlags); 
    ... 
end; 

通過訪問線程對象,你可以調用對象的方法,包括其自身的進步套路,所以下面可能構成的整體的獨立功能。它可以將其他所有內容委託給對象的方法。在這裏,我假定該方法具有與獨立函數相同的參數,但省略了lpData參數,因爲該參數將作爲Self參數隱式傳遞。

function CopyProgressRoutine; 
var 
    CopyThread: TCopyThread; 
begin 
    CopyThread := lpData; 
    Result := CopyThread.ProgressRoutine(TotalSize, TotalBytesTransferred, 
    StreamSize, StreamBytesTransferred, dwStreamNumber, 
    dwCallbackReason, hSourceFile, hDestinationFile); 
end; 
+0

設置'TProgressBar.Position'不需要'TThread.Synchronize' IMO。 'TProgressBar.SetPosition'方法從不分配控件的句柄,並通過自己切換線程上下文的'SendMessage'調用工作。 – kludg 2011-06-16 05:14:58

+7

從技術上講,@Serg,有一個競賽條件。 'TProgressBar'在讀取'Handle'屬性之前檢查'HandleAllocated'。如果句柄已被分配,但在讀取'Handle'之前被破壞,則句柄將被重新分配到錯誤的線程中。這不太可能發生,所以'TProgressBar'可能是安全的。但是,一般來說,UI更新應該與UI線程同步。 – 2011-06-16 05:51:14

+0

我可以在線程中聲明CopyCallback/ProgressRoutine函數嗎?我在@ProgressRoutine的CopyFileEx中得到錯誤:「需要變量」。 – maxfax 2011-06-16 11:22:04

相關問題