在一个线程中调用CopyFileEx和CopyCallback/ProgressRoutine函数(进度条位置将同步)是否可行和正确?
我能否在一个线程中声明CopyCallback/ProgressRoutine函数?我在CopyFileEx上得到错误:“需要变量”@ProgressRoutine。
在一个线程中调用CopyFileEx和CopyCallback/ProgressRoutine函数(进度条位置将同步)是否可行和正确?
我能否在一个线程中声明CopyCallback/ProgressRoutine函数?我在CopyFileEx上得到错误:“需要变量”@ProgressRoutine。
CopyFileEx
的线程上下文中被调用。如果你需要同步一些UI命令,请使用Delphi的常规TThread.Synchronize
或者其他你想要使用的线程间同步技术。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
。TProgressBar.SetPosition
方法从不分配控件的句柄,并通过SendMessage
调用自身切换线程上下文。 - kludgTProgressBar
在读取Handle
属性之前会检查HandleAllocated
。如果句柄已经被分配,但在读取Handle
之前被销毁,那么句柄将在错误的线程中重新分配。尽管这种情况不太可能发生,但TProgressBar
可能是安全的。总的来说,UI更新应该与UI线程同步。 - Rob Kennedy