XmlSchema在多线程应用程序中丢失其内容

时间:2012-08-30 00:20:08

标签: c# xml xsd

我有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在验证期间是否以某种方式被更改?为什么我的验证失败了?

2 个答案:

答案 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,因为现在多个线程无法访问该值。