如何在工作时暂停多文件复制?
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我假设您只是调用 File.Move
或 File.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您可以使用对象来表示不同的操作,例如
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 演示了如何进行手动文件复制。此答案显示了如何将操作排队以进行后台处理。如果您特别询问如何创建非模态进度条,我建议您发布一个新问题,或者自己尝试并在遇到困难时提出问题。 我可以像以前那样做和尝试,如果您现在有任何提示,我可以向您请教以上是关于如何在工作时暂停多文件复制?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 C# 的线程中以编程方式复制 Excel 文件时修复访问拒绝错误
如何从工作区中删除除您要保留的文件之外的所有文件? [复制]