3

XMLファイルを使用して、DBに存在する必要のない特定のデータを格納するアプリケーションがあります。このファイルは、めったにありませんが、同時にページ間で書き込まれる場合があります。これにより問題が発生し、おそらくページの1つがクラッシュします。他のファイルへの書き込みが完了するまでページレンダリングを待機させる方法があるかどうか疑問に思いました。

すべてのページレンダリングが独自のスレッドで実行されると想定できるかどうかはわかりません。もしそうなら、lock()コマンドのようにそのスレッドを停止して、リソースが利用可能になるのを待つことはできますか?もしそうなら、どうすればファイルにlock()を実装できますか(メモリセグメントではないため)?

スレッド化されていないか、lock()を使用できない場合、ファイルが確実に書き込まれるようにする他の方法はありますが、他の誰かがそのファイルを使用している場合は、ファイルが使用可能になるのを待つことができますか?

書き込みの順序と権限を管理する方法はたくさんありますが、これは簡単です。2番目に来た場合は、他の人が終わった後に書き込みます。この時点では、書き込みの衝突についてはそれほど心配していませんが、同時書き込みは対処する必要があるものです。

どんな助けでも大歓迎です!

4

3 に答える 3

2

編集:(モノラルで)さらにいくつかのテストを実行しますが、これが最善のアプローチかどうかはわかりません。

何もクラッシュしませんでしたがRun()、呼び出し元に戻る前に、実行が数秒間一時停止します。したがって、これはこのコードスニップを支持する良い兆候ではないと思います。

そうは言っても、テストされたシナリオは現実的とはほど遠いものです。


もう1つのオプションは、ファイルをFileShare.ReadWriteモードで開き、OSにロックを認識させることです。

    public void Run()
    {
        var file = @"/home/me/test.txt";
        var threads = new Thread[3];

        for (int i = 0; i < threads.Length; i++) {
            int j = i;
            threads[j] = new Thread( s => { 
            Console.WriteLine("thread " + j + " is running...");
            using (var stream = File.Open(file, FileMode.OpenOrCreate, 
                   FileAccess.ReadWrite, FileShare.ReadWrite))
            {
                Console.WriteLine("thread " + j + " is holding the file!");
                var data = ASCIIEncoding.ASCII.GetBytes("hello, I'm stream " + j);
                stream.Write(data, 0, data.Length);
                Thread.Sleep(1000);
            }});    
        }   

        foreach (var t in threads)
            t.Start();

        foreach (var t in threads)
            t.Join();

        Console.WriteLine(File.ReadAllText(file));
    }

出力:

thread 1 is running...
thread 0 is running...
thread 2 is running...
thread 2 is holding the file!
thread 1 is holding the file!
thread 0 is holding the file!
hello, I'm stream 0
于 2012-11-16T19:43:40.277 に答える
1

単一のマシンからのものである場合は、 http :Semaphore //msdn.microsoft.com/en-us/library/system.threading.semaphore.aspxを使用できます。

private static Semaphore _fileSemaphore = new Semaphore(1, 1, "myFileGlobalSemaphore");

// later...

try
{
    _fileSemaphore.WaitOne();
    // do stuff..
}
finally
{
    _fileSemaphore.Release();
}

これは、システム全体のロックのようなものです。しかし、素晴らしいとは言えませんが、DBを提案します。さらに、他のことが原因でファイルアクセスが失敗する可能性があります。適切なロックモードでを作成するものを実装できFileStreamます。これは、2つのソースによる書き込みのために開こうとすると失敗しますが、 (内部でクラスlockを使用する)同様のシナリオは実行されません。Monitor

ところで:「DBに保存する必要はありません」。あなたがこの質問をしているという事実は、それが本当にあるべきであることを示唆しています。それを実装するのが面倒な場合は、データアクセス戦略を再考することをお勧めします。CodeFirstを使用したEntityFrameworkのようなものを使用すると、DB内のものを非常に簡単に「チャック」できます。

于 2012-11-16T19:06:17.663 に答える
-2

グローバルロックオブジェクトを使用します。たとえば、global.asax.csに次のように追加します。

public static readonly object FileLock = new Object();

次に、ページで次を使用します。

lock(YourApplicationClass.FileLock)
{
    // do stuff
}
于 2012-11-16T19:07:38.527 に答える