使用C#(.NET 4.5),我想将一组文件复制到多个位置(例如将文件夹的内容复制到连接到计算机的2个USB驱动器)。有比仅使用foreach循环和File.Copy更有效的方法吗?
寻找(可能)的解决方案。
我的第一个想法是采用某种多线程方法。经过一些阅读和研究,我发现当涉及到IO时,仅盲目设置类型并/或异步进程不是一个好主意(如为什么Parallel.ForEach要比AsParallel().ForAll()快得多,即使MSDN建议相反?)。
瓶颈在于磁盘,特别是如果它是传统硬盘,因为它只能同步读写。这使我想到,如果我只读取一次,然后在多个位置输出数据,会怎样?毕竟,在我的USB驱动器场景中,我正在处理多个(输出)磁盘。
尽管如此,我仍然无法弄清楚如何做到这一点。我看到的一个想法(从多个线程复制同一文件到多个目标)是仅将每个文件的所有字节读入内存,然后循环遍历目标并将字节写入每个位置,然后再进入下一个文件。如果文件可能很大,那似乎不是一个好主意。我将要复制的一些文件将是视频文件,可能会有1 GB(或更多)。我无法想象将1 GB的文件加载到内存中只为将其复制到另一个磁盘?
因此,为了允许更大的文件灵活性,我最接近的代码如下(基于如何同时将一个文件复制到多个位置)。这段代码的问题在于我仍然没有进行单一读取和多路写入。它目前是多读和多写入。有没有一种方法可以进一步优化这段代码?我能够将块读入内存,然后将该块写入各个目标,然后再进入下一个块(就像上面的想法一样,但是使用分块的文件而不是整个文件)?
寻找(可能)的解决方案。
我的第一个想法是采用某种多线程方法。经过一些阅读和研究,我发现当涉及到IO时,仅盲目设置类型并/或异步进程不是一个好主意(如为什么Parallel.ForEach要比AsParallel().ForAll()快得多,即使MSDN建议相反?)。
瓶颈在于磁盘,特别是如果它是传统硬盘,因为它只能同步读写。这使我想到,如果我只读取一次,然后在多个位置输出数据,会怎样?毕竟,在我的USB驱动器场景中,我正在处理多个(输出)磁盘。
尽管如此,我仍然无法弄清楚如何做到这一点。我看到的一个想法(从多个线程复制同一文件到多个目标)是仅将每个文件的所有字节读入内存,然后循环遍历目标并将字节写入每个位置,然后再进入下一个文件。如果文件可能很大,那似乎不是一个好主意。我将要复制的一些文件将是视频文件,可能会有1 GB(或更多)。我无法想象将1 GB的文件加载到内存中只为将其复制到另一个磁盘?
因此,为了允许更大的文件灵活性,我最接近的代码如下(基于如何同时将一个文件复制到多个位置)。这段代码的问题在于我仍然没有进行单一读取和多路写入。它目前是多读和多写入。有没有一种方法可以进一步优化这段代码?我能够将块读入内存,然后将该块写入各个目标,然后再进入下一个块(就像上面的想法一样,但是使用分块的文件而不是整个文件)?
files.ForEach(fileDetail =>
Parallel.ForEach(fileDetail.DestinationPaths, new ParallelOptions(),
destinationPath =>
{
using (var source = new FileStream(fileDetail.SourcePath, FileMode.Open, FileAccess.Read, FileShare.Read))
using (var destination = new FileStream(destinationPath, FileMode.Create))
{
var buffer = new byte[1024];
int read;
while ((read = source.Read(buffer, 0, buffer.Length)) > 0)
{
destination.Write(buffer, 0, read);
}
}
}));
AsyncEnumerator
和 ForEachAsync。 - VMAtm