C# のParallel
クラスは、複数の処理を同時に実行する便利なクラスです。このクラスの基本的な使い方は以下の記事で紹介していますので、Parallel
クラスのことを初めて知った方は閲覧してみてください。

Parallel
クラスは複数の処理を同時に実行できるため、処理時間を大幅に短縮することができます。
この記事では、WPF アプリケーションでParallel.ForEach
を使ってファイルの出力を並列化するサンプルコードを紹介します。
ぜひ参考にしてみてください。

オススメの参考書
C#の使い方が丁寧に解説しており、「基礎からしっかりと学びたい」という初心者の方にオススメの一冊です。サンプルコードも記載してあり、各章の最後に復習問題があるので理解度を確認しながら読み進めることができます。新しい C# のバージョンにも対応している書籍です。
ファイル出力の並列化

アプリケーションを作成していると、複数の処理を同時に実行したい場面はよくあります。
例えば、ファイルを同時に出力するような場面で大容量のデータを出力する場合、単純に順番に処理だけでは時間がかかりすぎます。Parallel.ForEach
を使用すれば、処理を並列化できるので、大幅に処理時間を短縮できます。
ファイルの出力を並列化するコードは以下になります。
private void SaveLogFiles(List<string> fileNames)
{
// 並列処理オプションの設定
var option = new ParallelOptions();
option.MaxDegreeOfParallelism = 4;
Parallel.ForEach(fileNames, option, async name =>
{
try
{
Debug.WriteLine($"ファイル名: {name}");
// デスクトップに保存する
var filePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), name);
// ファイルをオープンする
using (StreamWriter sw = new StreamWriter(filePath, true, Encoding.UTF8))
{
for (int i = 0; i < 10000000; i++)
{
// テキストを書き込む
sw.WriteLine(i.ToString("00000000"));
}
}
Debug.WriteLine($"保存完了: {name}");
}
catch (Exception ex)
{
Debug.WriteLine($"保存失敗: {ex.Message}");
}
});
}
このサンプルではfor文のインデックスの値をファイルに書き込みます。疑似的に重たい処理を表現するためにループ回数は10,000,000回(1千万回)に設定しています。
ParallelOptions
で並列する最大スレッド数を4に設定しています。Parallel
はスレッドの上限を指定しない限り、自動的にスレッドをどんどん生成して並列処理を実行します。これはCPUの使用率を上げることになり、他のアプリケーションに影響する可能性があります。
WPF の 画面上にボタンを配置して、ボタンをクリックした時にSaveLogFiles
を実行するようにします。
private async void Button_Click(object sender, RoutedEventArgs e)
{
Debug.WriteLine("処理開始");
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
var names = new List<string>()
{
"A.txt",
"B.txt",
"C.txt",
"D.txt",
};
SaveLogFiles(names);
stopwatch.Stop();
Debug.WriteLine($"処理時間: {stopwatch.Elapsed.TotalSeconds.ToString("0.00")}sec");
}
実行結果は以下のようになります。
処理開始
ファイル名: A.txt
ファイル名: D.txt
ファイル名: B.txt
ファイル名: C.txt
保存完了: C.txt
保存完了: B.txt
保存完了: D.txt
保存完了: A.txt
処理時間: 2.58sec
Parallel.ForEach
メソッドを使用せず、単にforeach
メソッドでファイルに書き込みした時の処理時間と比較してみます。SaveLogFiles
のParallel.ForEach
メソッドをforeach
メソッドに置き換えます。
private void SaveLogFiles(List<string> fileNames)
{
// 並列処理オプションの設定
var option = new ParallelOptions();
option.MaxDegreeOfParallelism = 4;
foreach (var name in fileNames)
{
try
{
Debug.WriteLine($"ファイル名: {name}");
// デスクトップに保存
var filePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), name);
//ファイルをオープンする
using (StreamWriter sw = new StreamWriter(filePath, true, Encoding.UTF8))
{
for (int i = 0; i < 10000000; i++)
{
//テキストを書き込む
sw.WriteLine(i.ToString("00000000"));
}
}
Debug.WriteLine($"保存完了: {name}");
}
catch (Exception ex)
{
Debug.WriteLine($"保存失敗: {ex.Message}");
}
}
}
実行結果は以下のようになります。
処理開始
ファイル名: A.txt
保存完了: A.txt
ファイル名: B.txt
保存完了: B.txt
ファイル名: C.txt
保存完了: C.txt
ファイル名: D.txt
保存完了: D.txt
処理時間: 6.28sec
Parallel.ForEach
メソッドを使うことで、処理時間が6.28秒 → 2.58秒になっており、3.7秒短縮していることが分かります。
まとめ

この記事では Parallel クラスを使ったサンプルコードについて紹介をしました。
C# の Parallel クラスを使うことで、ファイル出力や大量データ処理の性能を大きく向上させることができます。この例を参考にして、自分のアプリに最適な並列化の処理を実装してみてください。



以上、最後まで読んでいただきありがとうございました。