2012-08-30 25 views
1

我有一个XmlSchema即时作为单例。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在验证过程中是否在某种程度上发生了变化?为什么我的验证失败?

+0

你是什么意思,“失去其内容”?你的意思是它变成了'空'吗? –

+0

@JohnSaunders我在那里犯了一个错误。我认为这已经使非公开的“文档”字段无效,但事实证明,从一开始就是空的。我的意思是尽管信息相同,但它停止工作。我上面编辑过。 –

+0

这好多了。现在,您需要做的就是告诉我们“停止工作”是什么意思:-) –

回答

1

谢谢你的所有意见和MiMo的回答!他们让我找到了解决方案。

看来,虽然我没有打电话给XmlSchema公众会员,但XmlDocument.Validate()方法是。 XmlSchema对象包含非线程安全的状态信息。

我将MessageShema更改为每线程单身人士。

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

它比我更愿意加载模式几次,但它现在起作用。这也意味着我可以删除MessageSchemaLock,因为现在不能由多个线程访问该值。

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; 
} 
+0

谢谢!我明白这在我的情况下会如何运作。不幸的是,这将打败我的服务的平行性质。 –