是否有可能从线程调用CopyFileEx和CopyCallback/ProgressRoutine函数(ProgressBar.Position将被同步)?CopyFileEx可以从辅助线程调用吗?
我可以在线程中声明CopyCallback/ProgressRoutine函数吗?我在@ProgressRoutine的CopyFileEx中得到错误:“需要变量”。
是否有可能从线程调用CopyFileEx和CopyCallback/ProgressRoutine函数(ProgressBar.Position将被同步)?CopyFileEx可以从辅助线程调用吗?
我可以在线程中声明CopyCallback/ProgressRoutine函数吗?我在@ProgressRoutine的CopyFileEx中得到错误:“需要变量”。
当然这是可能的。回调函数将在调用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;
设置'TProgressBar.Position'不需要'TThread.Synchronize' IMO。 'TProgressBar.SetPosition'方法从不分配控件的句柄,并通过自己切换线程上下文的'SendMessage'调用工作。 – kludg 2011-06-16 05:14:58
从技术上讲,@Serg,有一个竞赛条件。 'TProgressBar'在读取'Handle'属性之前检查'HandleAllocated'。如果句柄已被分配,但在读取'Handle'之前被破坏,则句柄将被重新分配到错误的线程中。这不太可能发生,所以'TProgressBar'可能是安全的。但是,一般来说,UI更新应该与UI线程同步。 – 2011-06-16 05:51:14
我可以在线程中声明CopyCallback/ProgressRoutine函数吗?我在@ProgressRoutine的CopyFileEx中得到错误:“需要变量”。 – maxfax 2011-06-16 11:22:04