3

書き込みのために、スレッドセーフな Linq-to-XML を保証する最良の方法は何ですか?

最近、Web クラスターが過負荷になり、サイトの応答性が向上したときに連絡できるように、overloaded.aspx をすぐに取り出さなければなりませんでした。私の短い5分間の速攻で、私はこれを書きました:

private static object LockHandle = new object();

protected override void OnLoad(EventArgs e)
{
  SubmitButton.ServerClick += new EventHandler(SubmitButton_ServerClick);
  base.OnLoad(e);
}

void SubmitButton_ServerClick(object sender, EventArgs e)
{
  string email = Email.Value.Trim();
  if (email.Length > 0)
  {
    Regex regex = new Regex(@"^([\w\-\.]+)@((\[([0-9]{1,3}\.){3}[0-9]{1,3}\])|(([\w\-]+\.)+)([a-zA-Z]{2,4}))$");
    if (regex.IsMatch(email))
    {
      lock (LockHandle)
      {
        try
        {
          string fileName = Server.MapPath("emails.xml");
          XDocument xdoc = XDocument.Load(fileName);
          xdoc.Element("emails").Add(new XElement("email", email));
          xdoc.Save(fileName);
        }
        catch {}
      }

      ResponseText.Text = "Thanks! We'll get back to you.";


    }
  }
}

Linq-to-XML がスレッドセーフであるかどうかを調べることができませんでした。そのため、理論は「静的オブジェクトをロックするだけで、複数の書き込みを防ぐことができます」というものになりました。これが最善のアプローチでしたか?それは必要でしたか (Linq-to-Xml スレッドセーフですか?)。悲しいことに、私の 2 冊の Pro LINQ と Linq in Action の本では、このテーマについて触れていません。

これは問題なく機能し、20 分間で過負荷になった量の電子メールをキャプチャしました。より良い方法があるかどうか疑問に思っています。または、そもそもロックするのがやり過ぎだった場合。

4

3 に答える 3

2

一般に、MSDN では、型または非静的メンバーがスレッド セーフとして明示的にマークされていない場合、それはそうではありません。通常、静的メンバーはそうあるべきです。

MS独自のガイドラインが守られていると仮定します。

ただし、グループのロード/編集/保存の実行中にファイルが変更されないように保護したいようです。そして、ロックを維持している場合にのみスレッドセーフになります (適切な読み取り/書き込みを使用して FileStram を直接作成し、それを (StreamReader または StreamWriter ラッパーを使用して) Load および Save メソッドに渡すと、これは十分に簡単です)。

ロックのみを使用することの欠点は、ファイルがロックされている場合、ファイル オープン メソッド (オブジェクト構築時に暗黙的に呼び出されるメソッドを含む) が例外をスローすることです。したがって、これを回避するにはロックが必要になる場合があります (複数のプロセスまたはアプリ ドメインが関与している場合は、ミューテックスが必要になる場合があります)。

于 2009-02-20T00:11:21.963 に答える
2

この方法でファイルを保存することは本質的にスレッド セーフではないため、静的ロック ハンドルを使用するのが賢明でした。

于 2009-02-20T00:21:54.137 に答える
1

LINQ オブジェクトは、.Net SDK オブジェクトが従うのと同じスレッド セーフ ガイドラインに従うと思います。

  • 静的メソッドの呼び出しは、スレッド間で同期する必要はありません
  • 同じインスタンス オブジェクトへの呼び出しは、スレッド間で同期する必要があります
于 2009-02-20T00:12:41.850 に答える