2016-07-02 4 views
2

異なるホストのさまざまなディレクトリから1つのディレクトリに多数のファイルをコピーしようとしています。それは非常に時間がかかることが判明し、このプログラムを何度も実行しなければならないので、各スレッドがプロセスを通じてXCOPYを実行するマルチスレッドの助けを借りてコードを変更しました。複数のスレッド生成プロセスが同じディレクトリにファイルをコピーするときのファイルエントリが見つかりませんC#

しかし、私はマルチスレッドコピーを行っているときに、いくつかのファイル(100未満、毎回変化する)がコピーされないことを知りました。私は同じディレクトリにXCOPYingするときに複数のプロセスが介在しているのか、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プロセスは、ディレクトリがシステム上に存在しないことをすべて検出すると同時にディレクトリを作成するように見えます)。 Parallel.Foreachに手動でスレッド管理を変更する

が問題を解決し、

か(私はなぜそれが同じ問題を作成していない考え出したていないが)、コードが見やすく作られた、汚れた修正がラップすることですEventWaitHandleでprocess.Start()を起動します。私は他の方法は、まず第一に、マルチプロセス

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

おそらくあなたはProcess.StartからStandardOutputを示すことができた...何かが私は、Dが –

+0

が起こっています上のコメントに直接返信する方法はわかりませんが、私はちょっと助けてくれてありがとうございます。提案したように、私は出力全体をリダイレクト/ダンプし、問題がどこにあるかを知りました。 –

+0

マルチスレッディングを使用してファイルをコピーするのは、ごくわずかです。あなたがCPUに束縛された操作を持っているなら、スレッドは有益です。 IOでは、CPUは事実上アイドル状態です。実際には、マルチスレッドIOはハードドライブ競合を導入し、**コピープロセスでエラー**を引き起こす可能性があるため、コピーを遅くする**ことができます。 – Enigmativity

答えて

0

を使用する目的を打ち負かすためではなくつのハンドルを使用するよりも先ディレクトリに基づいて異なるEventWaitHandleインスタンスを使用し、私はあなたがタスク指向のコードに切り替えることをお勧めこのような数のスレッドを作成すると、コンテキスト切り替えのためにパフォーマンスが低下する可能性があります。

あなたは簡単にこのようなパラレル拡張子、でこれを行うことができます。

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

第二に、あなたはエラーが@xとして、ProcessオブジェクトのプロパティStandardErrorをexamingによってXCOPY過程で発生した調べることができます。.. 。(あなたもそれを読み取る能力のためにそれをリダイレクトする必要がある)something like this、提案:

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

ありがとうございました。私はメッセージをファイルに投げ捨て、問題がどこにあるかを知った。エラーダンプファイルに「共有違反\ nディレクトリ<宛先ディレクトリ>を作成できません」と表示されます。私は、宛先ディレクトリのハッシュ値に基づいてwaitHandle(本質的にプロセス間レベルのロック)でprocess.Start()をラップし、ファイルはすべて正しくコピーされます。 Parallel.Foreachは確かにより好ましい方法です。私はwaitHandleを使わずに最初に試してみましたが、プログラムはうまくいきました(なぜ同じ問題に終わらないのか分かりませんでしたが)。 –

+0

@ T.L。私はその問題が、パラレル(parallel)アプローチによって解決されたと考えています。これは、ある程度のスレッドだけが一瞬で始まるので、レースは行われません。 – VMAtm

関連する問題