【发布时间】:2018-08-24 02:23:45
【问题描述】:
Windows API 函数 CopyFileEx 允许指定一个回调函数,当文件的一部分被复制到例如向用户提供有关进度的反馈。
这在我的程序中运行良好,但我现在有一个额外的要求:我需要暂时暂停复制过程,以便在一段时间内(可能长达几个小时)保持系统负载低,然后恢复它。这可能随时发生,并且通常有一个大文件(几个 100 GB)只被部分复制,因此中止进程并重新启动它不是一个好的选择,因为这意味着可能 99% 的文件已经被复制了,需要重新复制。
这样做的一个选择是简单地让执行复制的线程在调用回调时休眠,例如
function ProgressCallback(
_TotalFileSize, _TotalBytesTransferred, _StreamSize,
_StreamBytesTransferred: LARGE_INTEGER;
_StreamNumber, _CallbackReason: LongWord;
_SourceFile, _DestinationFile: THandle; _Data: Pointer): LongWord;
far; stdcall;
begin
// [...]
while gblPauseFlag do
sleep(100);
end;
(这当然是简化的代码。原始代码太复杂,无法在此处发布。)gblPauseFlag 将由应用程序中检查暂停条件的不同线程设置和重置。
我知道有更好的方法来暂停线程(事件、关键部分或其他),但这里的问题只是:在回调函数中暂停复制线程是否安全?还是会阻止某些 Windows 功能或资源?
从示例代码中可以看出,这是一个 Delphi 程序,但我认为这并不重要,所以我没有将问题标记为 [delphi]。
编辑:我可以传递标志 COPY_FILE_RESTARTABLE,但是:
在复制失败时在目标文件中跟踪复制的进度。 失败的副本可以在稍后重新启动,方法是指定相同的 lpExistingFileName 和 lpNewFileName 的值与调用中使用的值相同 那失败了。 这会显着减慢复制操作,因为 在复制操作期间,新文件可能会被多次刷新。
所以我宁愿尽量避免这种情况。
【问题讨论】:
-
这是安全的。在这种情况下,您只暂停您的线程。
-
WTF 我的问题被否决了吗?请至少留下一条评论来解释该投票!
-
您可能应该解释一下,为什么显而易见的解决方案(从您的 CopyProgresssRoutine 返回
PROGRESS_STOP)对您不起作用。 -
@IInspectable 这需要
COPY_FILE_RESTARTABLE标志。来自参考:“这会显着减慢复制操作” -
@RbMm 这得到了this question的确认。
标签: winapi file-copying