これを解決すると、いくつかの可能性のうちの 1 つが残されます...
- 進行状況が表示されない
- 計算に初期費用を使用する (Windows など)
- コストを計算しながら操作を実行する
速度がそれほど重要で、大きなディレクトリ ツリーが予想される場合は、これらのオプションの最後に頼ります。リンクされた質問Get all files and directory in specific path fast に回答を追加しました。これは、現在使用しているファイルとサイズよりも高速にカウントする方法を示しています。これをオプション #3 のマルチスレッド コードに組み合わせるには、次の手順を実行します...
static void Main()
{
const string directory = @"C:\Program Files";
// Create an enumeration of the files we will want to process that simply accumulates these values...
long total = 0;
var fcounter = new CSharpTest.Net.IO.FindFile(directory, "*", true, true, true);
fcounter.RaiseOnAccessDenied = false;
fcounter.FileFound +=
(o, e) =>
{
if (!e.IsDirectory)
{
Interlocked.Increment(ref total);
}
};
// Start a high-priority thread to perform the accumulation
Thread t = new Thread(fcounter.Find)
{
IsBackground = true,
Priority = ThreadPriority.AboveNormal,
Name = "file enum"
};
t.Start();
// Allow the accumulator thread to get a head-start on us
do { Thread.Sleep(100); }
while (total < 100 && t.IsAlive);
// Now we can process the files normally and update a percentage
long count = 0, percentage = 0;
var task = new CSharpTest.Net.IO.FindFile(directory, "*", true, true, true);
task.RaiseOnAccessDenied = false;
task.FileFound +=
(o, e) =>
{
if (!e.IsDirectory)
{
ProcessFile(e.FullPath);
// Update the percentage complete...
long progress = ++count * 100 / Interlocked.Read(ref total);
if (progress > percentage && progress <= 100)
{
percentage = progress;
Console.WriteLine("{0}% complete.", percentage);
}
}
};
task.Find();
}
FindFile クラスの実装はFindFile.csにあります。
ファイル処理タスク (上記の ProcessFile 関数) のコストに応じて、大量のファイルの進行状況が非常にきれいに表示されるはずです。ファイル処理が非常に高速な場合は、列挙の開始と処理の開始の間のラグを増やしたい場合があります。
イベント引数はFindFile.FileFoundEventArgs型であり、変更可能なクラスであるため、値が変更されるため、イベント引数への参照を保持しないようにしてください。
理想的には、エラー処理を追加し、おそらく両方の列挙を中止する機能を追加する必要があります。列挙を中止するには、イベント引数に「CancelEnumeration」を設定します。