我正在构建一个复制文件和文件夹的工作应用程序,还有一些选项,但在这个问题上没有使用这些选项。
有问题的函数遍历目录中的每个文件,然后将文件复制到新位置的相同目录中(因此它保留了嵌套文件结构)。
该应用程序是一个Windows窗体,由于同时写入文本框的问题,我已经在Task.Factory.StartNew()中包含了并行函数,修复了该问题。
Task.Factory.StartNew(() =>
{
Parallel.ForEach(Directory.GetFiles(root, "*.*", SearchOption.AllDirectories), newPath =>
{
try
{
File.Copy(newPath, newPath.Replace(root, destination), false);
WriteToOutput("recreated the file '" + newPath.Replace(root, destination) + "'");
}
catch (Exception e)
{
WriteToOutput(e.Message);
}
});
});
运行时,诊断工具每隔几秒显示一次尖峰。我怎样才能“走出去”'这些峰值并使性能保持一致?我也在为每个移动的文件写入屏幕,每个可能的20/25文件之间有一个明显的第二次停顿。
以下屏幕截图是诊断工具的示例。
答案 0 :(得分:5)
您的工作主要是IO绑定,而不是CPU绑定。你不会拥有任何CPU的工作来完成大部分时间。您只是在等待硬盘驱动器 的工作。 CPU完成一次操作后,CPU中的峰值只是很短的一段时间,CPU试图找出下一步要求它做什么,这需要很少的时间,因此为什么你会看到尖峰,而不是高原。
答案 1 :(得分:3)
我担心这句话:
由于同时写入文本框的问题,我在Task.Factory.StartNew()中包围了并行函数,修复了该问题
老实说,我怀疑修复了这个问题。它可能隐藏了它。您似乎没有等待或检查任务,因此您没有观察到任何异常。短暂的CPU峰值和输出延迟很容易引起某种堆栈的放松。
如果您无法从工作线程更新UI,请确保了解Invoke的用途,并确保使用它。然后摆脱StartNew
,或确保你正在处理任何例外。
答案 2 :(得分:1)
您正在做的是并行地按下具有许多文件读取请求的磁盘。好吧,与任何其他I / O设备一样,磁盘在该模式下也不能正常工作。
首先,如果您正在阅读硬盘,那么它肯定无法回答并行请求,因为它必须同时将阅读头移动到多个位置。
即使使用SDD,设备也无法以与CPU可以询问的速率相同的速率应答请求。
在任何情况下,磁盘肯定无法以统一的速度返回数据。许多文件读取请求将在整个永恒期间(以CPU时间测量)处于待处理状态,从而阻止这些任务。这就是为什么在使用许多并行操作来攻击磁盘时性能不均匀的原因。
尝试处理多个文件时,您可以选择分配一个任务来读取它们,然后并行处理加载的数据。想想那个设计。 I / O绑定任务只有一个,并且不会被阻止超过必要的任务。这将使驱动器以当前可以实现的最大速度返回数据。显然,CPU绑定任务是非阻塞的,因为在任何任务启动时它们的数据已经存在于内存中。我希望这种设计能够提供流畅的性能。