25

次のファイル読み取りコードを使用します。

using (FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.None))
{
    using (TextReader tr = new StreamReader(fileStream))
    {
        string fileContents = tr.ReadToEnd();
    }
}

そして、次のファイルはコードを書きます:

using (TextWriter tw = new StreamWriter(fileName))
{
    tw.Write(fileContents);
    tw.Close();
}

次の例外の詳細が表示されます。

別のプロセスで使用されているため、プロセスはファイル 'c:\temp\myfile.txt' にアクセスできません。

これを回避する最善の方法は何ですか? リーダーは例外を受け取ったときに再試行する必要がありますか、それとももっと良い方法がありますか?

リーダー プロセスはFileSystemWatcherを使用して、ファイルがいつ変更されたかを認識していることに注意してください。

また、この例では、2 つのプロセス間で文字列を共有する別の方法を探しているわけではないことに注意してください。

4

8 に答える 8

38

書き込み用にファイルを開き、書き込みアクセスのみをロックして、他のユーザーが引き続きファイルを読み取ることができるようにします。

例えば、

using (FileStream stream = new FileStream(@"C:\Myfile.txt", FileMode.Open, FileAccess.ReadWrite, FileShare.Read))
{
   // Do your writing here.
}

その他のファイル アクセスでは、書き込みではなく読み取り用にファイルが開かれ、読み書き共有が許可されます。

using (FileStream stream = new FileStream(@"C:\Myfile.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
   // Does reading  here.
}

リーダーが常に最新のファイルを読み取るようにしたい場合は、誰かがファイルに書き込んでいることを示すロック ファイルを使用する必要があります (ただし、慎重に実装しないと競合状態になる可能性があります)。排他アクセスを取得するまで再試行できるように、例外を読み取りおよび処理するために開くときに、必ず書き込み共有をブロックしてください。

于 2008-10-21T14:35:54.560 に答える
7

名前付きミューテックスを作成すると、書き込みアプリケーションでミューテックスを定義し、ミューテックスが解放されるまで読み取りアプリケーションを待機させることができます。

したがって、現在 FileSystemWatcher で動作している通知プロセスでは、mutex を待機する必要があるかどうかを確認するだけです。必要な場合は、待機してから処理します。

これは、私が見つけたこのようなMutexのVB の例です。C# に変換するのは簡単なはずです。

于 2008-10-21T14:37:14.853 に答える
3

ファイルが書き込まれている場合は、ファイルのステータスをチェックするプロセスを取得します。これは、ロック ファイルの存在によって行うことができます (つまり、この別のファイルが存在すると、空になる可能性があり、メイン ファイルへの書き込みが防止されます)。

ただし、2 つのプロセスが同時にロック ファイルを作成する可能性があるため、これでもフェイルセーフではありませんが、書き込みをコミットする前にこれを確認できます。

プロセスがロック ファイルに遭遇した場合は、単純にスリープ/待機させてから、事前定義された間隔で再試行します。

于 2008-10-21T14:38:05.337 に答える
3

FileShare.None でファイルを開く特定の理由はありますか? これにより、ファイルが他のプロセスによって開かれなくなります。

FileShare.Write または FileShare.ReadWrite は、他のプロセス (パーミッションに応じて) がファイルを読み込んでいる間にファイルを開いて書き込むことを許可する必要がありますが、読み込んでいる間にファイルが変更されていることに注意する必要があります。開封時の内容がここで役立つ場合があります。

ただし、これらの回答はすべて等しく有効です。最適な解決策は、ファイルで何をしようとしているのかによって異なります。変更されないことを保証しながら読み取ることが重要な場合は、ロックして後続の例外を処理します。あなたの書き込みコードで; 同時に読み書きすることが重要な場合は、FileShare 定数を変更してください。

于 2008-10-21T14:51:10.333 に答える
2

Mutexこれにはオブジェクトを使用できます。

于 2008-10-21T14:32:04.893 に答える
2

リーダーとライターの両方に再試行メカニズムが必要です。また、 FileShareは、リーダーの場合はFileShare.readに設定し、ライターの場合はFileShare.noneに設定する必要があります。これにより、書き込み中にリーダーがファイルを読み取らないようにする必要があります。

リーダー(リトライを除く)は

using (FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
{
    using (TextReader tr = new StreamReader(fileStream))
    {
        string fileContents = tr.ReadToEnd();
    }
}

ライター (再試行を除く) は次のようになります。

FileStream fileStream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None);
using (TextWriter tw = new StreamWriter(fileStream))
{
    tw.Write(fileContents);
    tw.Close();
}
于 2008-10-21T15:02:26.737 に答える
1

一時ファイルに書き込みます。書き込みが終了したら、リーダーが探している場所や名前にファイルの名前を変更/移動します。

于 2008-10-21T14:44:29.083 に答える