2

ファイルを読み取るための次のコードがあります

StreamReader str = new StreamReader(File.Open(fileName, FileMode.Open, FileAccess.Read));
string fichier = str.ReadToEnd();
str.Close();

これはasp.net Webサービスの一部であり、本番環境で1年間正常に動作しています. 現在、サーバーの負荷が増加しているため、顧客は「ファイルは既に使用されています」というエラーを受け取り始めています。そのファイルはこのコードから読み取られており、アプリケーションから書き込まれることはありません。

私が明確に見ている問題の 1 つは、後で使用するためにファイルの内容をキャッシュしていないことです。私たちはそれを行います。しかし、この問題が発生する理由と方法を理解する必要があります。

複数のスレッドがファイルを読み込もうとしていることが原因ですか? StreamReader はスレッド セーフではないことを読みましたが、読み取りモードでファイルを開くときに問題になるのはなぜですか?

4

2 に答える 2

3

読み取りアクセスを許可してファイルを開く必要があります。このオーバーロードを使用してFile.Open、ファイル共有モードを指定します。を使用FileShare.Readして、このファイルへの読み取りアクセスを許可できます。

別の可能な解決策は、このファイルをクラスの静的コンストラクターでメモリに一度ロードし、その内容を静的な読み取り専用変数に格納することです。静的コンストラクターは 1 回だけ実行されることが保証されており、スレッドセーフであるため、動作させるために特別なことをする必要はありません。

メモリの内容をまったく変更しない場合は、データにアクセスするときにロックする必要さえありません。内容を変更する場合は、変更しようとするたびに最初にこのデータを複製する必要がありますが、実際の元のデータは決して変更されないため、複製操作のロックは必要ありません。

例えば:

public static class FileData
{
    private static readonly string s_sFileData;

    static FileData ()
    {
        s_sFileData = ...; // read file data here using your code
    }

    public static string Contents
    {
        get
        {
            return ( string.Copy ( s_sFileData ) );
        }
    }
}

これにより、データがカプセル化され、読み取り専用アクセスが可能になります。

コードがファイルの内容を変更する可能性がある場合にのみ必要String.Copy()です。これは、元の文字列を保護するために新しい文字列インスタンスを強制的に作成するための予防措置です。は不変であるためstring、これはコードで文字列ポインターを使用する場合にのみ必要です。キャッシュされたデータへのポインターを使用した先週、自分のコードで同様の変数の問題に遭遇したため、このビットを追加しただけです。:)

于 2012-11-01T02:29:23.610 に答える
1

FileMode は、何ができるか (読み取り/書き込み) を制御するだけです。

ファイルへの共有アクセスはオペレーティング システム レベルで処理され、FileShare (3 番目のパラメーター) で動作を要求できます。ドキュメントを参照してください。

于 2012-11-01T02:31:00.943 に答える