2011-06-16 43 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

相关问题