使用Linq-to-XML和线程插入数据

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是否线程安全)? 遗憾的是,我的两本Pro LINQ和Linq in Action书籍都没有涉及到这个主题。

这种方法很有效,在我们超载的20m中捕获了大量电子邮件。只是想知道是否有更好的方法;或者,如果一开始就锁定它是否过度处理了。

3个回答

2
一般来说,在MSDN上,如果一个类型或非静态成员没有明确标记为线程安全,则它就不是线程安全的。通常情况下,静态成员应该是线程安全的。假设遵循了微软自己的指南。
然而,您似乎想要在执行加载/编辑/保存组时保护文件不被更改。只有在维护锁定的情况下才是线程安全的(如果您直接使用具有适当读/写权限的FileStram并将其传递给Load和Save方法,则这很容易实现)。
仅使用锁定的缺点是,打开文件的方法(包括隐式调用的对象构造方法)将抛出异常,如果文件被锁定,因此您可能需要使用锁定来避免这种情况(如果涉及多个进程或应用程序域,则可能需要使用互斥锁)。

我的想法是,我不希望其他写入操作失败,而是等待它们轮流写入同一个文件。我的想法是通过创建一个静态对象并锁定它,这将阻止所有其他线程(在相同的命名空间中)进行写入。对还是错? - eduncan911
s/namespace/app-domain/,是的。 但这与XDocument无关,而是涉及文件和并发。使用List<byte>加载/操作/保存时也会遇到相同的问题。 - Richard

2

这种方式保存文件本身不是线程安全的,因此使用静态锁句柄是明智的选择。


1

我猜LINQ对象遵循与任何.Net SDK对象相同的线程安全指南:

  • 对静态方法的调用不需要在线程之间进行同步
  • 对同一实例对象的调用应在线程之间进行同步

是的,没错。除非出了问题,不然这只是猜测。所以我才会选择这条路。呵呵。 - eduncan911
也许我应该说“期望”而不是“猜测”。当您使用System命名空间中的组件时,这是您可以视为理所当然的事情。 - Frank Schwieterman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接