当多个线程生成的进程将文件复制到同一个目录c#时,缺少文件条目

本文关键字:文件 同一个 复制 线程 进程 | 更新日期: 2023-09-27 17:54:14

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

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

List<Thread> threadList = new List<Thread>;
foreach(FileEntry fileEntry in fileEntries)
{
    Thread thread = new Thread(() => {
        //full path of file, like ''host'directory'directoryB'fileA.txt
        string filePath = fileEntry._filePath;
        //name of file, like fileA.txt
        string file = fileEntry._file;
        //dumpDirectory is where I want to copy all the files to
        string destPath = Path.Combine(dumpDirectory, file);
        //each file here is either a directory or a real file, bad naming convention I know...(open to suggestions if any)
        string fileType = File.Exists(filePath) ? "f" : "d";
        using (Process process = new Process())
        {
            process.StartInfo.CreateNoWindow = true;
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.FileName = "cmd.exe";
            process.StartInfo.Arguments = string.Format(@"/C echo {0} | XCOPY /E /C /H /R /K /O /Y {1} {2}", fileType, filePath, destPath);
            Console.WriteLine("copying {2} [{0}] to destination [{1}]", filePath, destPath, string.Compare(fileType, "f") == 0 ? "file" : "directory");
            process.Start();
            process.WaitForExit();
            if (process.ExitCode != 0)
            {
                Console.WriteLine("encountered problems when copying file [{0}]", filePath);
            }
        }
    });
    thread.Start();
    threadList.Add(thread);
}
foreach(Thread thread in threadList)
{
    thread.Join();
}

--------------------------- 错误修正如下 -------------------------------

所以根据下面的回复建议(感谢大家的快速回复,节省了我的周末^_^),我重定向了进程输出,发现问题是"共享违规'n无法创建目录"。Xcopy在将多个文件复制到同一目录时出现问题(当各种Xcopy进程都检测到该目录在系统上不存在时,它们似乎同时创建了一个目录)。

将手动线程管理更改为并行。Foreach解决了这个问题,并使代码看起来更好(虽然我还没有弄清楚为什么它没有创建相同的问题)

或者,一个更脏的修复是用EventWaitHandle封装process.Start()。我根据目标目录使用了不同的EventWaitHandle实例,而不是使用一个句柄,因为另一种方法会破坏使用多进程的目的

//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();
}

当多个线程生成的进程将文件复制到同一个目录c#时,缺少文件条目

首先,我建议您切换到面向任务的代码,因为在如此多的线程上创建可能会由于上下文切换而导致性能下降。

你可以很容易地用并行扩展做到这一点,像这样:

Parallel.ForEach(fileEntries, fileEntry => { // YOUR code here };

第二,您可以通过检查Process对象的StandardError属性来调查XCOPY进程中发生的错误,如@x…建议这样做(您还必须重定向它才能读取它):

process.StartInfo.RedirectStandardError = true;
// ...
if (process.ExitCode != 0)
{
    Console.WriteLine("encountered problems when copying file [{0}]", filePath);
    Console.WriteLine(process.StandardError.ReadToEnd());
}