Por supuesto que es posible. Se llamará a la función de devolución de llamada en el contexto del hilo que llama al CopyFileEx
. Si necesita sincronizar algunos comandos de la interfaz de usuario, use el habitual TThread.Synchronize
de Delphi, o cualquier otra técnica de sincronización entre hilos que desee.
La función de devolución de llamada no puede ser un método de la clase de subproceso. Debe coincidir con la firma dictada por la API, por lo que debe ser una función independiente. Cuando lo haya declarado correctamente, no necesitará usar el operador @
cuando lo pase al CopyFileEx
.
function CopyProgressRoutine(TotalFileSize, TotalBytesTransferred: Int64;
StreamSize, StreamBytesTransferred: Int64;
dwStreamNumber, dwCallbackReason: DWord;
hSourceFile, hDestinationFile: THandle;
lpData: Pointer): DWord; stdcall;
le puede dar el acceso a las funciones de devolución de llamada al objeto de procesos asociado con el parámetro lpData
. Pasa una referencia al objeto hilo para ese parámetro cuando se llama CopyFileEx
:
procedure TCopyThread.Execute;
begin
...
CopyResult := CopyFileEx(CurrentName, NewName, CopyProgressRoutine, Self,
@Cancel, CopyFlags);
...
end;
Con acceso al objeto hilo, puede llamar a métodos en ese objeto, incluyendo su propia rutina de progreso, por lo que el siguiente podría constituir la totalidad de la función independiente. Puede delegar todo lo demás a un método de su objeto. Aquí he supuesto que el método tiene todos los mismos parámetros que la función independiente, excepto que omite el parámetro lpData
porque se va a pasar implícitamente como el parámetro Self
.
function CopyProgressRoutine;
var
CopyThread: TCopyThread;
begin
CopyThread := lpData;
Result := CopyThread.ProgressRoutine(TotalSize, TotalBytesTransferred,
StreamSize, StreamBytesTransferred, dwStreamNumber,
dwCallbackReason, hSourceFile, hDestinationFile);
end;
Configuración 'TProgressBar.Position' no requiere' TThread.Synchronize' IMO. El método 'TProgressBar.SetPosition' nunca asigna el control y funciona a través de la llamada' SendMessage' que cambia el contexto del hilo por sí mismo. – kludg
Técnicamente, @Serg, hay una condición de carrera. 'TProgressBar' comprueba' HandleAllocated' antes de leer la propiedad 'Handle'. Si el identificador ya estaba asignado, pero se destruye antes de leer 'Handle', el asa se reasignará en el subproceso incorrecto. Es poco probable que suceda, por lo que 'TProgressBar' probablemente sea seguro. En general, sin embargo, las actualizaciones de UI deben sincronizarse con el hilo de UI. –
¿Puedo declarar la función CopyCallback/ProgressRoutine en un hilo? Aparece el error: "Variable required" en CopyFileEx en @ProgressRoutine. – maxfax