我有XmlSchema
即时作为单身人士。
public static XmlSchema MessageSchema
{
get
{
lock (MessageSchemaLock)
{
// If this property is not initialised, initialise it.
if (messageSchema == null)
{
// Read XSD from database.
string xsd = Database.Configuration.GetValue("MessageBaseXsd");
using (TextReader reader = new StringReader(xsd))
{
messageSchema = XmlSchema.Read(reader, (sender, e) => {
if (e.Severity == XmlSeverityType.Error) throw e.Exception;
});
}
}
}
// Return the property value.
return messageSchema;
}
}
private static XmlSchema messageSchema = null;
private static readonly object MessageSchemaLock = new object();
此架构用于验证进入系统的每个文档。以下方法执行验证。
/// <summary>
/// Validates the XML document against an XML schema document.
/// </summary>
/// <param name="xml">The XmlDocument to validate.</param>
/// <param name="xsd">The XmlSchema against which to validate.</param>
/// <returns>A report listing all validation warnings and errors detected by the validation.</returns>
public static XmlSchemaValidationReport Validate(XmlDocument xml, XmlSchema xsd)
{
XmlSchemaValidationReport report = new XmlSchemaValidationReport();
xml.Schemas.Add(xsd);
xml.Validate((sender, e) => { report.Add(e); });
xml.Schemas.Remove(xsd);
return report;
}
XmlSchemaValidationReport
包含一个'List'和一些辅助方法,没有任何东西可以看到XmlSchema
对象。
当我在多个线程上验证消息时,Validate
方法在处理完前几条消息后失败。它报告说其中一个元素丢失了,尽管我一天都清楚地看到它。我的测试是多次发送相同的消息,每个消息都是单独的XmlDocument
。我仔细检查过MessageSchema
属性是唯一设置messageSchema
字段的代码。
XmlSchema
在验证期间是否以某种方式被更改?为什么我的验证失败了?
答案 0 :(得分:1)
XmlSchema
类不是线程安全的 - 我不确定验证是否尝试修改它,但是从报告的问题看来似乎是这种情况。你可以试试
public static XmlSchemaValidationReport Validate(XmlDocument xml, XmlSchema xsd)
{
XmlSchemaValidationReport report = new XmlSchemaValidationReport();
lock (xsd) {
xml.Schemas.Add(xsd);
xml.Validate((sender, e) => { report.Add(e); });
xml.Schemas.Remove(xsd);
}
return report;
}
答案 1 :(得分:1)
感谢所有评论和MiMo的回答!他们引导我找到解决方案。
似乎虽然我没有呼叫任何XmlSchema
公共成员,但XmlDocument.Validate()
方法是。 XmlSchema
对象包含非线程安全的状态信息。
我将MessageShema
更改为每线程单例。
public static XmlSchema MessageSchema { ... }
[ThreadStatic]
private static XmlSchema messageSchema;
它比我更愿意加载模式几次,但它现在可以工作了。这也意味着我可以删除MessageSchemaLock
,因为现在多个线程无法访问该值。