C# 多线程生成的进程将文件复制到同一目录C时缺少文件项#

C# 多线程生成的进程将文件复制到同一目录C时缺少文件项#,c#,multithreading,cmd,multiprocessing,xcopy,C#,Multithreading,Cmd,Multiprocessing,Xcopy,我试图将大量文件从不同主机上的不同目录复制到单个目录。由于它非常耗时,而且我必须多次运行该程序,因此我更改了代码以利用多线程的帮助,每个线程通过一个进程执行XCOPY 然而,我发现当我进行多线程复制时,有些文件(少于100个,每次都不同)没有被复制。我还没有弄清楚这是因为当XCOPY复制到同一个目录时,多个进程相互干涉,还是更多的是XCOPY问题(不确定它对同一目标上的多进程调用的支持程度) 首先,我建议您切换到面向任务的代码,因为创建这样数量的线程可能会因为上下文切换而导致性能下降 您可以通过

我试图将大量文件从不同主机上的不同目录复制到单个目录。由于它非常耗时,而且我必须多次运行该程序,因此我更改了代码以利用多线程的帮助,每个线程通过一个进程执行XCOPY

然而,我发现当我进行多线程复制时,有些文件(少于100个,每次都不同)没有被复制。我还没有弄清楚这是因为当XCOPY复制到同一个目录时,多个进程相互干涉,还是更多的是XCOPY问题(不确定它对同一目标上的多进程调用的支持程度)


首先,我建议您切换到面向任务的代码,因为创建这样数量的线程可能会因为上下文切换而导致性能下降

您可以通过并行扩展轻松实现这一点,如下所示:

Parallel.ForEach(fileEntries, fileEntry => { // YOUR code here };
其次,您可以通过检查
process
对象的
StandardError
属性来调查
XCOPY
过程中发生的错误,如@x。。。建议,(您还必须重定向它以获得阅读能力):


也许您可以显示流程的标准输出。开始。。。这里发生了一些事情,我不知道如何直接回复上述评论,但我只想感谢[x…]的帮助。正如建议的那样,我重定向/转储了整个输出,并找到了问题所在。使用多线程复制文件没有什么意义。如果有CPU限制的操作,线程是有益的。使用IO时,CPU实际上处于空闲状态。事实上,多线程IO会减慢复制速度,因为会引入硬盘争用,并且会在复制过程中导致错误。@据我所知,Enigmatity争用和错误确实发生过,我必须实现lock或parallel.foreach()以使其正常工作。然而,速度提升是非常明显的(2~4倍我没有计算)。源文件位于远程主机上,目标是服务器上的目录。根据您对IO绑定任务的解释,我猜原始复制文件任务更多地受这些远程主机的网络带宽的限制。在作业并行之前,它可能从未达到目标服务器的硬件限制。非常感谢。我将这些信息转储到一个文件中,并找出问题所在。错误转储文件中显示“共享冲突\n无法创建目录”。我使用基于目标目录的哈希值的waitHandle(本质上是进程间级别锁)包装了process.Start(),并且所有文件都被正确复制。不过,Parallel.Foreach绝对是一种更受欢迎的方法。我先尝试了一下,没有使用waitHandle,程序运行得很好(尽管我没有找到为什么它没有陷入同样的麻烦)。@T.L.我认为这个问题是通过
并行
方法解决的,因为它在一瞬间只启动给定数量的线程,所以竞争不会发生。
//name the wait handle based on destination value
EventWaitHandle destWaitHandle = new EventWaitHandle(true, EventResetMode.AutoReset, string.Format("waitHandle{0}", destPath.GetHashCode()));

//only trigger the wait handle lock if the file being copied from (and to) is a directory. Based on the error log info XCopy seemed to never have issues with copying individual files
//and the program worked fine if I only put the lock at directory level
if (string.Compare(fileType, "d") == 0)
{
    destWaitHandle.WaitOne();
}

process.Start();

//this line was added to write error messages into respective files during the process' execution
process.BeginErrorReadLine();
process.WaitForExit();

if (string.Compare(fileType, "d") == 0)
{
    destWaitHandle.Set();
}
Parallel.ForEach(fileEntries, fileEntry => { // YOUR code here };
process.StartInfo.RedirectStandardError = true;
// ...
if (process.ExitCode != 0)
{
    Console.WriteLine("encountered problems when copying file [{0}]", filePath);
    Console.WriteLine(process.StandardError.ReadToEnd());
}