【问题标题】:Unable to write to XML file using threads and XDocument无法使用线程和 XDocument 写入 XML 文件
【发布时间】:2019-05-10 11:33:20
【问题描述】:
string filepath = Environment.CurrentDirectory + @"Expense.xml";

public void  WriteToXML(object param)
{
Expense exp = (Expense)param;
   if (File.Exists(filepath)) {
    XDocument xDocument = XDocument.Load(filepath);

    XElement root = xDocument.Element("Expenses");
    IEnumerable<XElement> rows = root.Descendants("Expense");
    XElement firstRow = rows.First();

    firstRow.AddBeforeSelf(new XElement("Expense",
           new XElement("Id", exp.Id.ToString()),
           new XElement("Amount", exp.Amount.ToString()),
           new XElement("Contact", exp.Contact),
           new XElement("Description", exp.Description),
           new XElement("Datetime", exp.Datetime)));
    xDocument.Save(filepath);
 }
}

Expense exp = new Expense();
exp.Id = new Random().Next(1, 10000);
exp.Amount = float.Parse(text1[count].Text);
exp.Contact = combo1[count].SelectedItem.ToString();
exp.Description = rtext1[count].Text.ToString();
exp.Datetime = DateTime.Now.ToString("MM-dd-yyyy");

workerThread = new Thread(newParameterizedThreadStart(WriteToXML));
workerThread.Start(exp); // throws System.IO.IOException

我无法使用工作线程写入 XML 文件 - 我收到此错误:

System.IO.IOException: '进程无法访问文件 'C:\work\FinanceManagement\FinanceManagement\bin\DebugExpense.xml' 因为它正被另一个进程使用。

但如果我像WriteToXML(exp); 一样使用它,它就可以工作。我认为XDocument.Load(filepath) 不是线程安全的。我该如何解决这个问题?

【问题讨论】:

  • 第一行不应该是:string filepath = Path.Combine(Environment.CurrentDirectory, "Expense.xml") 吗?看来您的意思是 bin\Debug\Expense.xml 的路径
  • 一次是否有多个线程?
  • @Crowcoder 我使用 File.Exists(filepath) 检查文件是否存在。我已经更新了代码。
  • File.Exists 容易受到竞争条件的影响。如果您的线程非常接近地运行,您可以同时在该代码块中获得多个线程。
  • @Metheny 我的坏。感谢您的指出。

标签: c# xml linq-to-xml worker-thread


【解决方案1】:

尝试介绍lock,看看能否解决问题:

// Declare this somewhere in your project, can be in same class as WriteToXML
static object XmlLocker;

然后将lock 包裹在逻辑周围:

public void WriteToXML(object param)
{
    Expense exp = (Expense)param;

    lock (XmlLocker) // <-- this limits one thread at a time
    {
        if (File.Exists(filepath))
        {
            XDocument xDocument = XDocument.Load(filepath);

            XElement root = xDocument.Element("Expenses");
            IEnumerable<XElement> rows = root.Descendants("Expense");
            XElement firstRow = rows.First();

            firstRow.AddBeforeSelf(new XElement("Expense",
                   new XElement("Id", exp.Id.ToString()),
                   new XElement("Amount", exp.Amount.ToString()),
                   new XElement("Contact", exp.Contact),
                   new XElement("Description", exp.Description),
                   new XElement("Datetime", exp.Datetime)));
            xDocument.Save(filepath);
        }
    }
}

【讨论】:

    猜你喜欢
    • 2015-09-21
    • 1970-01-01
    • 1970-01-01
    • 2016-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多