1

我有一个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列表”和一些辅助方法,没有任何东西可以看到该XmlSchema对象。

当我在多个线程上验证消息时,在Validate处理前几条消息后该方法失败。它报告说其中一个元素丢失了,尽管我看得很清楚。我的测试是多次发送相同的消息,每次都作为单独的XmlDocument. 我仔细检查了该MessageSchema属性是唯一设置该messageSchema字段的代码。

在验证期间是否以XmlSchema某种方式被改变?为什么我的验证失败?

4

2 回答 2

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; 
} 
于 2012-08-30T19:13:58.150 回答
1

感谢您的所有评论和 MiMo 的回答!他们让我找到了解决方案。

似乎虽然我没有调用任何XmlSchema公共成员,但XmlDocument.Validate()方法是。该XmlSchema对象包含非线程安全的状态信息。

我将其更改MessageShema为每线程单例。

public static XmlSchema MessageSchema { ... }
[ThreadStatic]
private static XmlSchema messageSchema;

它加载模式的次数比我想要的多,但它现在可以工作了。这也意味着我可以删除该MessageSchemaLock值,因为现在多个线程无法访问该值。

于 2012-08-31T00:34:41.433 回答