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的值与调用中使用的值相同 失败了。 这可能会大大减慢复制操作的速度 在复制操作期间,可能会多次刷新新文件。
所以我宁愿尽量避免这种情况。
答案 0 :(得分:-1)
理想情况下,如果要复制的文件很大,则应该对大型文件使用robocopy之类的实用程序。如果仍然喜欢编写自己的实用程序,请使其实用程序可以重新启动已终止的副本。您可以使用文件流在目标文件中存储有关复制进度的元数据。