C#でファイルの書き込みと読み込みを並行で実行する方法

2024年12月26日木曜日

C#

t f B! P L

C#で、ファイルの「読み込み」と「書き込み」を並行に実行し、整合性を保ちながらファイルを共有する際のポイントを解説します。

はじめに

ファイルへのアクセスは、書き込みや読み込みが重なると整合性が失われたり、例外が発生したりする可能性があります。特に、複数のスレッドやプロセスが同時に操作する場合、適切なロック機構を用いなければデータの破損が起こります。C#ではFileStreamFileAccessFileShareオプションを使用することで、これらの問題を解決できます。

ファイルの共有方法

C#では、FileStreamクラスを使用してファイルを操作します。この際、以下の2つのポイントを押さえておくことが重要です。

  1. FileAccess: ファイルへのアクセスモードを指定します(読み取り、書き込み、またはその両方)。
  2. FileShare: 他のプロセスやスレッドがファイルにアクセスできる方法を指定します。

サンプルコード

以下に、ファイルの書き込みと読み込みを並行して実行するコード例を示します。

using System;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    private const string FilePath = "shared_file.txt";

    static async Task Main(string[] args)
    {
        // 書き込みタスク
        var writeTask = Task.Run(() => WriteToFile());

        // 読み込みタスク
        var readTask = Task.Run(() => ReadFromFile());

        await Task.WhenAll(writeTask, readTask);
    }

    static void WriteToFile()
    {
        for (int i = 0; i < 10; i++)
        {
            using (var fileStream = new FileStream(FilePath, FileMode.Append, FileAccess.Write, FileShare.Read))
            using (var writer = new StreamWriter(fileStream, Encoding.UTF8))
            {
                string content = $"Line {i}: {DateTime.Now}\n";
                writer.Write(content);
                Console.WriteLine($"書き込み: {content}");
            }

            Thread.Sleep(500); // 書き込み間隔
        }
    }

    static void ReadFromFile()
    {
        for (int i = 0; i < 10; i++)
        {
            using (var fileStream = new FileStream(FilePath, FileMode.Open, FileAccess.Read, FileShare.Write))
            using (var reader = new StreamReader(fileStream, Encoding.UTF8))
            {
                string content = reader.ReadToEnd();
                Console.WriteLine($"読み込み: {content}");
            }

            Thread.Sleep(1000); // 読み込み間隔
        }
    }
}

コードのポイント

FileShareオプションの使用

まず、書き込み時にFileShare.Readを指定することで、他のプロセスが読み込み操作を行うことを許可します。そして、読み込み時にFileShare.Writeを指定することで、他のプロセスが書き込み操作をすることを許可しています。そうすることで、書き込みと読み込みを同時に実行できるようにします。

逐次アクセスの制御

今回の例では、書き込んだ内容がファイルに反映されると、読み込み側に即座に反映されます。 一定の単位で読み込み側に反映したい場合は、より高度な同期制御(例: SemaphoreMutex)を検討してください。

バッファサイズの調整

ファイルの読み書きパフォーマンスを最適化するためには、FileStreamのバッファサイズを適切に設定することが重要です。特に、大容量データを処理する場合や高頻度アクセスが必要な場合には効果的です。

実行結果

このプログラムを実行すると、書き込み操作と並行して読み込み操作が行われます。コンソールには、以下のような出力が表示されます。

書き込み: Line 0: 2024-12-26 12:00:00
読み込み: Line 0: 2024-12-26 12:00:00
書き込み: Line 1: 2024-12-26 12:00:01
読み込み: Line 0: 2024-12-26 12:00:00
読み込み: Line 1: 2024-12-26 12:00:01

まとめ

この記事では、C#でファイルの書き込みと読み込みを並行して実行する方法を解説しました。FileStreamFileAccessFileShareオプションを活用することで、整合性を保ちながらファイルを安全に共有できます。用途に応じてロック機構やパフォーマンスチューニングを適用し、最適なファイル操作を実現してください。

スポンサーリンク
スポンサーリンク

このブログを検索

Profile

自分の写真
Webアプリエンジニア。 日々新しい技術を追い求めてブログでアウトプットしています。
プロフィール画像は、猫村ゆゆこ様に書いてもらいました。

仕事募集もしていたり、していなかったり。

QooQ