1

フォーム デザイナーとして機能する Web サイト アプリケーションがあります。

フォームデータは XML ファイルに保存されます。各フォームには独自の xml ファイルがあります。

フォームを編集するときは、基本的に XML ファイルを再作成します。

public void Save(Guid form_Id, IEnumerable<FormData> formData)
{
    XDocument doc = new XDocument();
    XElement formsDataElement = new XElement("FormsData");
    doc.Add(formsDataElement);
    foreach (FormData data in formData)
    {
        formsDataElement.Add(new XElement("FormData",
                                 new XAttribute("Id", data.Id)
                                 new XAttribute("Name", data.Name)
                                 // other attributes
                             ));
    }

    doc.Save(formXMLFilePath);
}

これはうまく機能しますが、2 人のユーザーが同時に XML ファイルを更新しないようにしたいと考えています。どうにかしてロックしたい。

各ファイルの保存プロセスを個別にロックするにはどうすればよいですか?

以下のように保存機能をロックすることもできますが、別の XML ファイルを保存したとしても、すべてのユーザーがロックされます。

private static readonly object _lock = new object();
public void Save(Guid form_Id, IEnumerable<FormData> formData)
{
    lock(_lock)
    {
        XDocument doc = new XDocument();
        foreach (FormData data in formData)
        {
            // Code
        }

        doc.Save(formXMLFilePath);
    }
}
4

3 に答える 3

2

ファイルが同時に書き込まれるのを防ぐために、メソッドは次のコンストラクターを使用して をXDocument.Save内部的に作成します。FileStream

new FileStream(
    outputFileName,
    FileMode.Create,
    FileAccess.Write,
    FileShare.Read,
    0x1000,
    UseAsync)

このオプションFileShare.Readは、複数の書き込みが同時に発生するのを防ぎます。2 つの書き込みを同時に実行しようとすると、IOExceptionスローされてしまいます。

この不測の事態に対処するためのコードを書きたいと思うかもしれません。この回答https://stackoverflow.com/a/50800/138578は、ロックされているファイルを処理し、ファイルが利用可能になるまで再試行する方法を正確に提供する必要があります。

ドキュメントが小さくて多い場合は、このような状況に頻繁に遭遇することはありません。

于 2013-01-14T10:45:43.547 に答える
1

次のようなものを試してください。

FileStream file = new FileStream(formXMLFilePath,FileMode.Create,FileAccress.Write,FileShare.None);

try {
    doc.Save(file);
} finally {
    file.Close();
}

これはを使用し、モードFileStreamを提供しFileShareます。この例では、ファイルに書き込むことができるように、ファイルを排他的にロックしています。

ただし、これは単に、ロックがあるため、後続の書き込みが失敗することを意味します。

この問題を回避するために、私はキューを持っている傾向があり、唯一の仕事はキューを処理してファイルシステムに書き込むことです。

ただし、別の解決策は、単にファイルにアクセスしてみることです。それが失敗した場合は、少し待ってから再試行してください。これにより、lockアクセスできるようになるまで待機してから続行するのと同じようなことができます。

private static bool IsLocked(string fileName)
{
    if (!File.Exists(fileName)) return false;

    try {
        FileStream file = new FileStream(fileName,FileMode.Open,FileAccess.Write,FileShare.None);

        try {
            return false;
        } finally {
            file.Close();
        }
    } catch (IOException) {
        return true;
    }
}

public void Save(Guid form_Id, IEnumerable<FormData> formData)
{
    while (IsLocked(formXMLFilePath)) Thread.Sleep(100);

    FileStream file = new FileStream(formXMLFilePath,FileMode.Create,FileAccress.Write,FileShare.None);

    try {
        doc.Save(file);
    } finally {
        file.Close();
    }
}
于 2013-01-14T10:36:44.470 に答える
0

xmlファイルを開いた後にxmlファイル接続を閉じていません。したがって、関数の最後に最初に接続を閉じる必要があると思います。

あなたはこれを使うことができます

filename.Close();

これがお役に立てば幸いです

于 2013-01-14T10:37:03.787 に答える