3

ファイル ストリームを使用し、 に設定FileShareするNoneと、同じ関数に同時にアクセスする 2 人のユーザーがそのファイルの読み取り/書き込みを行いたいとします。2 番目のユーザーの要求を待機させますFileShare.Noneか、それとも 2 番目のユーザーの要求は例外をスローしますか?

//two users get to this this code at the same time

using (FileStream filestream = new FileStream(chosenFile, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None))
using (StreamReader sr = new StreamReader(filestream))
using (StreamWriter sw = new StreamWriter(filestream))
{
    //reading and writing to file
}

Msdn のコメント: なし 現在のファイルの共有を拒否します。(このプロセスまたは別のプロセスによる) ファイルを開く要求は、ファイルが閉じられるまで失敗します。

しかし、ファイルストリームが閉じられるまでリクエストは試行され続けますか?

4

2 に答える 2

3

プロセスが読み取り/書き込み用にファイルを開くFileShare.Noneと、この同じファイルに対する任意のプロセスによる後続のアクセスが発生しAcess Denied Exceptionます。あなたの質問に答えるために、2 番目のユーザーは例外を取得します。

MSDN : FileShare.None - 現在のファイルの共有を拒否します。(このプロセスまたは別のプロセスによる) ファイルを開く要求は、ファイルが閉じられるまで失敗します。


この種の同時ファイル アクセスの問題を処理する方法は多数あります。次のコードは、この状況に対処する簡単な方法を示しています。

//Retry 5 times when file access fails
int retryCounter = 5;

while (!isFileAccessSuccess && retryCounter > 0)
{
    try
    {
       //Put file access logic here

        //If the file has been accessed successfully set the flag to true
        isFileAccessSuccess = true;
    }
    catch (Exception exception)
    {
        //Log exception
    }
    finally
    {
        //Decrease the retry count
        --retryCounter;
    }

    if (!isFileAccessSuccess)
    {
        //Wait sometime until initiating next try
        Thread.Sleep(10000);
    }
}
于 2015-06-12T09:42:31.050 に答える
3

いいえ、 withとIOExceptionがスローされますHResult = -2147024864Message = The process cannot access the file 'path' because it is being used by another process.

ファイルへのアクセスを同期する場合は、名前付き待機ハンドルを使用できます。

public class FileAcessSynchronizer
{
    private readonly string _path;
    private readonly EventWaitHandle _waitHandle;

    public FileAcessSynch(string path)
    {
        _path = path;
        _waitHandle =  new EventWaitHandle(true, EventResetMode.AutoReset, "NameOfTheWaitHandle");
    }

    public void DoSomething()
    {
        try
        {
            _waitHandle.WaitOne();
            using (FileStream filestream = new FileStream(chosenFile, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None))
            using (StreamReader sr = new StreamReader(filestream))
            using (StreamWriter sw = new StreamWriter(filestream))
            {
                //reading and writing to file
            }
        }
        finally
        {
            _waitHandle.Set();
        }
    }
}

名前付き待機ハンドルはクリティカル セクションを作成するため、(待機ハンドル名と同じ名前を使用する) アプリケーションの 2 つのスレッドまたはプロセスは、その中のコードを同時に実行できません。したがって、1 つのスレッドまたはプロセスがセクションに入り、誰もアクセスできない方法でファイルを開き (他のアプリケーション)、コマンドを実行し、最後にクリティカル セクションを離れて、アプリケーションの他のスレッドまたはプロセスがクリティカル セクションに入ることができるようにします。

于 2015-06-12T09:51:20.833 に答える