架构验证错误/ XmlSchemaSet的线程安全性?

时间:2009-09-28 12:23:08

标签: c# thread-safety

下午好,

XML架构验证代码段在开发/ q& a环境中正常运行,但在Production中产生了一些奇怪的验证结果。通常的怀疑是代码对于线程是不安全的,并且生产方案的额外负载正在消除错误。

具体情况如下。请考虑验证的XML是:

<mssql:spExecute type="ResultSet" xmlns:mssql="urn:namespace">
    <mssql:actor>IPASS</mssql:actor>
    <mssql:connection>ConnectionString</mssql:connection>
    <mssql:storedProcedure>dbo.RedFox</mssql:storedProcedure>
</mssql:spExecute>

在一整天的过程中,大约300次执行(> 2M)会产生以下异常:

System.Xml.Schema.XmlSchemaValidationException
The 'http://www.w3.org/2000/xmlns/:mssql' attribute is not declared.

架构验证器似乎抱怨名称空间声明。

代码结构如下:

  • 有一个XmlSchemaSet的静态实例;
  • 正在以线程安全的方式初始化XmlSchemaSet实例;
  • 每个工作线程都使用相同的XmlSchemaSet;
  • 在XmlSerializer.Deserialize()调用期间进行验证,使用XmlReader和使用ValidationType.Schema初始化的XmlReaderSetting。

有关可能导致验证通过命名空间声明阻塞的内容的任何想法吗?

3 个答案:

答案 0 :(得分:4)

  1. 您所描述的是受控实验的结果或 从生产环境观察? 如果是后者,请尝试在受控设置中重现它以确保其他一些 错误不是一个真正的原因。

  2. The documentation for XmlSchemaSet说:

      

    “不保证任何实例成员都是线程安全的。”

    这包括属性读取和“只读”方法。 所以我们不能假设XmlSchemaSet的只读使用是线程安全的。 直到Microsoft提供明确允许共享相同编译的实现 线程之间的架构表示,唯一安全的做法就是不共享。

  3. OTOH分享单个编译的不可变XmlSchemaSet来验证是合乎逻辑的 多个XmlDocument(或XmlReader)个实例。 这是一个非常明智的场景,所以我不明白为什么它没有明确 允许并记录在案。

    (更新:显然Java's standard XML library明确保证这一点。 为什么在.NET中不是这样?)

答案 1 :(得分:2)

这可以在.NET 4.0中修复,但不记录。

我在生产网络服务中遇到了同样的错误。错误类似,并且在峰值活动期间是随机的:“ xxx元素未声明”。但是在我的例子中,我们只是使用循环读取命令来验证XML,而不是序列化对象。

该服务是在.NET 3.5下构建/运行的,在开发环境中,我可以通过启动5个线程并同时进行服务调用来轻松复制此错误。该错误大约发生在10个请求中。

当我坐下来解决这个问题时,我做的第一件事就是将服务升级到.NET 4.0。一旦我这样做,我就不能再产生这个错误了。我增加了线程数并删除了服务限制 - 仍然没有错误。

虽然当前的文档仍然表明XmlSchema实例操作不能保证线程安全,但似乎在3.5和4.0之间进行了一些框架更改,这提高了XmlSchema上读/验证类型操作的线程安全性。

答案 2 :(得分:1)

我遇到了同样的问题。似乎XML验证不是只读操作,本文指出:

http://blogs.msdn.com/xmlteam/archive/2009/04/27/xmlschemaset-thread-safety.aspx

锁定它解决了我的问题。