在CopyFileEx的回调中阻止是否安全?

时间:2018-03-15 10:11:33

标签: winapi file-copying

Windows API函数CopyFileEx允许指定回调函数,然后在将文件的一部分复制到例如文件时调用该函数。向用户提供有关进度的反馈。

这在我的程序中工作正常,但我现在有一个额外的要求:我需要暂时暂停复制过程,以便将系统负载保持低一段时间(可能长达几个小时),然后恢复它。这可能在任何时候发生,通常有一个大文件(几个100千兆字节),只是部分复制,所以中止该过程并重新启动它不是一个好的选择,因为这意味着可能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的值与调用中使用的值相同   失败了。 这可能会大大减慢复制操作的速度   在复制操作期间,可能会多次刷新新文件。

来源:CopyFileEx documentation

所以我宁愿尽量避免这种情况。

1 个答案:

答案 0 :(得分:-1)

理想情况下,如果要复制的文件很大,则应该对大型文件使用robocopy之类的实用程序。如果仍然喜欢编写自己的实用程序,请使其实用程序可以重新启动已终止的副本。您可以使用文件流在目标文件中存储有关复制进度的元数据。