无法使用线程和 XDocument 写入 XML 文件
Unable to write to XML file using threads and XDocument
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
我无法使用 worker treads 写入 XML 文件 - 我收到此错误:
System.IO.IOException: 'The process cannot access the file 'C:\work\FinanceManagement\FinanceManagement\bin\DebugExpense.xml' because it is being used by another process.
但如果我像 WriteToXML(exp);
那样使用它,它就会起作用。我认为 XDocument.Load(filepath)
不是线程安全的。我该如何解决这个问题?
尝试引入一个 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);
}
}
}
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
我无法使用 worker treads 写入 XML 文件 - 我收到此错误:
System.IO.IOException: 'The process cannot access the file 'C:\work\FinanceManagement\FinanceManagement\bin\DebugExpense.xml' because it is being used by another process.
但如果我像 WriteToXML(exp);
那样使用它,它就会起作用。我认为 XDocument.Load(filepath)
不是线程安全的。我该如何解决这个问题?
尝试引入一个 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);
}
}
}