如何在工作时暂停多文件复制?

Posted

技术标签:

【中文标题】如何在工作时暂停多文件复制?【英文标题】:How can I pause multi-file copy when one is working? 【发布时间】:2021-06-06 08:20:27 【问题描述】:

我开始了一个有趣的小项目,我非常喜欢它,我开始扩展它。我需要一个简单的文件资源管理器(如 Windows 一个)来查看和打开文件,但现在扩展它我有多个文件的问题,我想从目录 A 复制一些并将它们粘贴到 B 然后在这样做时我想复制目录 C 中的一些文件并将它们粘贴到 D 中,如果副本 A -> B 正在进行中,则副本 C -> D 将暂停,当副本 A -> B 完成时,可以开始第二个副本。目前,我可以将文件从 A 复制到 B。有什么不太复杂的东西可以尝试吗?

我在开始复制时使用新表单来显示进度条、文件名、文件计数和大小,并且我使用的是 BackgroundWorker

【问题讨论】:

真正的问题是什么?如何对操作进行排队以便一次运行一个? @JonasH 是的,也许如何正确处理要复制的文件历史记录。现在,我做的最好的就是一个 List ,其中包含完整路径(带文件名),当我粘贴时,我使用 filestream 并使用列表复制文件,但我确信这不是最好的主意处理历史 【参考方案1】:

我假设您只是调用 File.MoveFile.Copy 那些没有暂停实际操作的能力,您必须编写自己的移动/复制操作

例如。要复制文件,您可以执行以下操作

public void CopyFile(string sourceFileName, string destFileName, bool overwrite)

    var outputFileMode = overwrite ? FileMode.Create : FileMode.CreateNew;

    using (var inputStream = new FileStream(sourceFileName, FileMode.Open, FileAccess.Read, FileShare.Read))
    using (var outputStream = new FileStream(destFileName, outputFileMode, FileAccess.Write, FileShare.None))
    
        const int bufferSize = 16384; // 16 Kb
        var buffer = new byte[bufferSize];

        int bytesRead;

        do
        
            bytesRead = inputStream.Read(buffer, 0, bufferSize);
            outputStream.Write(buffer, 0, bytesRead);
         while (bytesRead == bufferSize);
    

现在您有了这段代码,您可以简单地添加一个带有条件的 while 循环以“暂停”代码,例如。

while (_pause)

    Thread.Sleep(100);

这个while 会从上面的代码进入do 循环。

这里是完整的想法

public void CopyFile(string sourceFileName, string destFileName, bool overwrite)

    var outputFileMode = overwrite ? FileMode.Create : FileMode.CreateNew;

    using (var inputStream = new FileStream(sourceFileName, FileMode.Open, FileAccess.Read, FileShare.Read))
    using (var outputStream = new FileStream(destFileName, outputFileMode, FileAccess.Write, FileShare.None))
    
        const int bufferSize = 16384; // 16 Kb
        var buffer = new byte[bufferSize];

        int bytesRead;

        do
        

            //run this loop until _pause = false
            while (_pause)
            
                Thread.Sleep(100);
            


            bytesRead = inputStream.Read(buffer, 0, bufferSize);
            outputStream.Write(buffer, 0, bytesRead);
         while (bytesRead == bufferSize);
    

【讨论】:

"我假设您只是调用 File.Move 或 File.Copy" 不,文件流。昨天换了,因为好多了。 while (_pause) _pause 是怎么设置的? _pause 只是我假设单击按钮时必须设置的字段 因为我在完成复制时关闭了进度条表单,所以我可以使用 Worker_RunWorkerCompleter => _pause = false (这不是我将使用的代码) 我给了你一个大概的思路,如果你想有一个 100% 的解决方案,你只需要复制和粘贴,我恐怕会需要更多信息,你现在在做什么东西,因为我对你的代码知之甚少,我根本无法告诉你如何/在哪里调用它 好吧,我需要一种更好的方法来处理文件历史记录,但是......我有一个进度条窗口表单,当我在上下文菜单中单击复制时,它将完整的文件路径保存在 List 然后在粘贴我做 new ProgressBarWindow(itemsToCopy //List, fileFolder // 源。我稍后删除文件名,filePath.Text, false //overwrite);我可以将代码发送到某个地方,我不知道该怎么做。附:您的 [输入/输出] 流不起作用,进度条永远不会更新,也不会写入任何内容【参考方案2】:

您可以使用对象来表示不同的操作,例如

public interface IFileOperation 
    void Execute(Func<double> ReportProgress, CancellationToken cancel);

然后您可以创建一个包含多个操作的队列,并在另一个线程上创建一个任务来处理每个项目

private CancellationTokenSource cts = new CancellationTokenSource();
public double CurrentProgress get; private set;
public void CancelCurrentOperation() => cts.Cancel();
public BlockingCollection<IFileOperation> Queue = new BlockingCollection<IFileOperation>(new ConcurrentQueue<IFileOperation>());
public void RunOnWorkerThread()
     foreach(var op in Queue .GetConsumingEnumerable())
         cts  = new CancellationTokenSource();
         CurrentProgress  = 0;
          op.Execute(p => Progress = p, cts.Token );
     
 

这将在后台线程上一次运行一个文件操作,同时允许从主线程添加新操作。要报告进度,您需要一个非模态进度条。 IE。您应该在 UI 的某处添加进度条控件,而不是显示对话框。否则,您将无法在不取消当前操作的情况下添加新操作。您还需要一些方法将进度条连接到当前正在运行的操作,例如通过在主线程上运行一个计时器来更新进度条绑定到的属性。您可以将该方法作为长时间运行任务运行,也可以作为专用线程运行。

如果您愿意,您可以向 FileOperation 添加暂停/恢复方法。 Rand Random 的答案显示了如何手动复制文件,因此我将在此处跳过。您还可以创建一个 UI,显示所有排队文件操作的列表,并允许删除排队的任务。您甚至可以通过更多工作并行运行多个操作,并为每个操作显示单独的进度。

【讨论】:

我不需要暂停/恢复(目前)。我有一个进度条的表单,但看起来这是一个不好的选择,我可以删除它并在主表单中添加一个进度条,我需要找到如何正确实现所有内容 @code9 这个问题有点宽泛。 Rand Random 演示了如何进行手动文件复制。此答案显示了如何将操作排队以进行后台处理。如果您特别询问如何创建非模态进度条,我建议您发布一个新问题,或者自己尝试并在遇到困难时提出问题。 我可以像以前那样做和尝试,如果您现在有任何提示,我可以向您请教

以上是关于如何在工作时暂停多文件复制?的主要内容,如果未能解决你的问题,请参考以下文章

iOS:如何判断应用程序何时暂停? [复制]

如何在 C# 的线程中以编程方式复制 Excel 文件时修复访问拒绝错误

如何从工作区中删除除您要保留的文件之外的所有文件? [复制]

如何相对于角色复制带有ansible的文件?

如何使用 JavaScript 暂停 HTML5 视频? [复制]

linux如何复制文件夹下所有文件但不复制子目录