6

Webサービスから取得され、Webアプリケーション内にローカルにキャッシュされたデータのXML表現であるファイルがあります。このデータは非常に静的ですが、変更される可能性があるという考え方です。そこで、ファイルにキャッシュするように設定し、モニターを貼り付けて、削除されているかどうかを確認しました。削除されると、ファイルはソースから更新されて再構築されます。

ただし、マルチスレッド環境では、ファイルの読み取り/書き込み中にデータにアクセスしようとしているため、明らかに問題が発生しています。

これは、ロックするオブジェクトを追加したため、混乱を招きます。これは、読み取り/書き込み中は常にロックされます。他のスレッドからのアクセスの試みは、ロックが解除されるまで「待機」するように指示されるというのが私の理解でしたか?

お知らせするために、私はマルチスレッド開発に本当に慣れていないので、これが私の側の混乱であることを完全に受け入れます:)

  • 私は何かが足りないのですか?
  • マルチスレッド環境での最良のファイルアクセス戦略は何ですか?

編集

申し訳ありませんが、これはASP.NET2.0を使用していると言っておくべきでした:)

4

5 に答える 5

7

ファイルが別のプロセスによってロックされていないことを確認するために使用するコードを次に示します。100% 誰にでもできるわけではありませんが、ほとんどの場合、これで作業が完了します。

    /// <summary>
    /// Blocks until the file is not locked any more.
    /// </summary>
    /// <param name="fullPath"></param>
    bool WaitForFile(string fullPath)
    {
        int numTries = 0;
        while (true)
        {
            ++numTries;
            try
            {
                // Attempt to open the file exclusively.
                using (FileStream fs = new FileStream(fullPath,
                    FileMode.Open, FileAccess.ReadWrite, 
                    FileShare.None, 100))
                {
                    fs.ReadByte();

                    // If we got this far the file is ready
                    break;
                }
            }
            catch (Exception ex)
            {
                Log.LogWarning(
                   "WaitForFile {0} failed to get an exclusive lock: {1}", 
                    fullPath, ex.ToString());

                if (numTries > 10)
                {
                    Log.LogWarning(
                        "WaitForFile {0} giving up after 10 tries", 
                        fullPath);
                    return false;
                }

                // Wait for the lock to be released
                System.Threading.Thread.Sleep(500);
            }
        }

        Log.LogTrace("WaitForFile {0} returning true after {1} tries",
            fullPath, numTries);
        return true;
    }

もちろん、アプリケーションに合わせてタイムアウトと再試行を微調整できます。これを使用して、書き込みに時間がかかる巨大な FTP ファイルを処理します。

于 2008-09-03T12:33:29.370 に答える
1

静的として保存されているオブジェクトをロックしている場合、ロックは同じアプリケーションドメイン内のすべてのスレッドで機能するはずですが、問題のある行を確認できるように、コードサンプルをアップロードする必要があります。

とはいえ、IISがWebガーデンモード(つまり、アプリケーションを実行する複数のプロセス)で実行するように構成されているかどうかを確認すると、ロックロジックが破損する可能性があります。ミューテックスを使用してこのような状況を修正することはできますが、アプリケーションを再構成して単一のプロセスで実行する方が簡単ですが、Webガーデンの設定に影響を与える可能性があるため、パフォーマンスを確認することをお勧めします。パフォーマンス。

于 2008-09-03T08:15:13.267 に答える
1

一時的な名前 (「data.xml_TMP」) でファイルを作成し、準備ができたら名前を本来の名前に変更することもできます。そうすれば、準備が整う前に他のプロセスがアクセスすることはありません。

于 2008-09-03T09:17:52.583 に答える
1

OK、私はこれに取り組んでおり、ストレステストモジュールを作成して、基本的にいくつかのスレッドからコードのがらくたを打ち出しました(関連する質問を参照)。

この時点から、コードの穴を見つけるのがずっと簡単になりました。私のコードは実際にはそれほど遠くないことがわかりましたが、基本的に読み取り/書き込み操作がスタックする原因となる特定のロジックパスがありました。つまり、時間内にクリアされなかった場合、ブームになる!

それを取り出して、ストレステストを再度実行すると、すべて正常に機能しました!

そのため、ファイル アクセス コードで特別なことは何もしていませんlock。適切な場所 (つまり、読み取りまたは書き込み時) にステートメントを使用するようにしました。

于 2008-09-22T07:41:44.750 に答える
0

AutoResetEventスレッド間の通信に使用するのはどうですか? メソッドで約 8 GB のファイルを作成し、そのファイルをメソッドcreatefileでコピーするコンソール アプリを作成しましたmain

 static AutoResetEvent waitHandle = new AutoResetEvent(false);
    static string filePath=@"C:\Temp\test.txt";
    static string fileCopyPath=@"C:\Temp\test-copy.txt";
    static void Main(string[] args)
    {
        Console.WriteLine("in main method");
        Console.WriteLine();
        Thread thread = new Thread(createFile);
        thread.Start();

        Console.WriteLine("waiting for file to be processed ");
        Console.WriteLine();
        waitHandle.WaitOne();
        Console.WriteLine();

        File.Copy(filePath, fileCopyPath);
        Console.WriteLine("file copied ");

    }


    static void createFile()
    {

        FileStream fs= File.Create(filePath);            
        Console.WriteLine("start processing a file "+DateTime.Now);
        Console.WriteLine();
        using (StreamWriter sw = new StreamWriter(fs))
        {
            for (long i = 0; i < 300000000; i++)
            {
                sw.WriteLine("The value of i is " + i);

            }
        }
        Console.WriteLine("file processed " + DateTime.Now);
        Console.WriteLine();

        waitHandle.Set();
    }
于 2015-09-21T17:36:58.957 に答える