当多个线程生成的进程将文件复制到同一个目录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();
}
首先,我建议您切换到面向任务的代码,因为在如此多的线程上创建可能会由于上下文切换而导致性能下降。
你可以很容易地用并行扩展做到这一点,像这样:
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());
}