Multithreading – can copyfileex be called from a worker thread?
Is it possible to call copyfileex and copycallback / progressroutine functions from a thread (progressbar.position will be synchronized)?
Can I declare the copycallback / progressroutine function in the thread? I received an error in copyfileex on @ progressroutine: "variable required."
Solution
Of course it's possible The callback function will be invoked in the context of the thread calling CopyFileEx. If you need to synchronize some UI commands, please use Delphi's usual TThread Synchronize, or any other inter - thread synchronization technology you want
A callback function cannot be a method of a thread class It needs to match the signature specified by the API, so it needs to be a separate function When you declare it correctly, you do not need to use the @ operator when passing it to copyfileex
function CopyProgressRoutine(TotalFileSize,TotalBytesTransferred: Int64; StreamSize,StreamBytesTransferred: Int64; dwStreamNumber,dwCallbackReason: DWord; hSourceFile,hDestinationFile: THandle; lpData: Pointer): DWord; stdcall;
You can use the lpdata parameter to provide the callback function with access to the associated thread object When copyfileex is called, pass a reference to the thread object of this parameter:
procedure TCopyThread.Execute; begin ... CopyResult := CopyFileEx(CurrentName,NewName,CopyProgressRoutine,Self,@Cancel,CopyFlags); ... end;
By accessing a thread object, you can call methods on that object, including its own progress routine, so the following can form an entire independent function It can delegate everything else to the methods of your object Here I assume that the method has all the same parameters as the independent function, except that it omits the lpdata parameter because it will be passed implicitly as a self parameter
function CopyProgressRoutine; var CopyThread: TCopyThread; begin CopyThread := lpData; Result := CopyThread.ProgressRoutine(TotalSize,TotalBytesTransferred,StreamSize,StreamBytesTransferred,dwStreamNumber,dwCallbackReason,hSourceFile,hDestinationFile); end;