Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/268.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# XmlSchemaSet的架构验证错误/线程安全性?_C#_Thread Safety - Fatal编程技术网

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

C# XmlSchemaSet的架构验证错误/线程安全性?,c#,thread-safety,C#,Thread Safety,下午好 XML模式验证片段在开发/q&a环境中运行良好,但在生产环境中会产生一些奇怪的验证结果。通常的怀疑是代码对于线程来说是不安全的,并且生产场景的额外负载正在清除错误 具体情况如下。考虑到正在验证的XML是: <mssql:spExecute type="ResultSet" xmlns:mssql="urn:namespace"> <mssql:actor>IPASS</mssql:actor> <mssql:connection&

下午好

XML模式验证片段在开发/q&a环境中运行良好,但在生产环境中会产生一些奇怪的验证结果。通常的怀疑是代码对于线程来说是不安全的,并且生产场景的额外负载正在清除错误

具体情况如下。考虑到正在验证的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>

IPASS
连接串
红狐狸
在一整天中,大约300次执行(超过200万次)会产生以下例外情况:

System.Xml.Schema.XmlSchemaValidationException The 'http://www.w3.org/2000/xmlns/:mssql' attribute is not declared. System.Xml.Schema.XmlSchemaValidationException 这个http://www.w3.org/2000/xmlns/:mssql'属性未声明。 模式验证器似乎在抱怨名称空间声明

代码结构如下:

  • 存在XmlSchemaSet的静态实例
  • XmlSchemaSet实例的初始化是以线程安全的方式进行的
  • 每个工作线程使用相同的XmlSchemaSet
  • 验证发生在XmlSerializer.Deserialize()调用期间,使用XmlReader,XmlReaderSettings使用ValidationType.Schema初始化

有没有想过是什么原因导致命名空间声明阻塞了验证?

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

在它周围加上一把锁为我解决了这个问题

  • 你所描述的是受控实验的结果还是 从生产环境观察? 如果是后者,请尝试在受控设置中复制,以确保其他 bug不是真正的原因

  • 说:

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

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

  • 因此,共享单个编译的不可变
    XmlSchemaSet
    进行验证似乎是合乎逻辑的 多个
    XmlDocument
    (或
    XmlReader
    )实例。 这是一个非常合理的场景,所以我不明白为什么它没有明确的定义 允许并记录

    (更新:很明显,这在中得到了明确的保证。 为什么在.NET中不是这样?)


  • 这可能在.NET 4.0中得到修复,但没有记录在案

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

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

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


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

    否。事实并非如此。再读一遍。文章说,验证只在
    XmlSchemaSet
    上使用只读操作,因此多个线程可以共享单个
    XmlSchemaSet
    实例,而无需显式锁定。它指出a)
    XmlSchemaSet
    构造不是线程安全的,b)您需要确保您提供的
    ValidationEventHandler
    回调是线程安全的。两者都很明显。它没有说明为什么假定
    XmlSchemaSet
    上的只读操作确实是线程安全的。文档中说“任何实例成员[包括属性读取--ts]都不能保证线程安全。”您能详细说明一下吗?只读的定义是什么?在.NET Framework中,“只读操作”是什么意思,是否有官方定义?如果一个操作是只读的,那么如何从外部查看一个类呢?请记住,任何类型的延迟求值都会导致一个操作,该操作在外部为只读时会更改对象的内部状态。对于使用前编译的
    XmlSchemaSet
    ,期望所有读取都是真正的只读是有意义的。问题是,文档并没有公开这么说,我不确定是否可以安全地缓存已编译的模式。还要注意,如果这不起作用,我可能会在启动时创建一个XmlSchema对象列表,并包装对它们的访问,以便每个线程只使用一个。我相信创建对象会带来一些成本,最好不要每次请求都创建一个。好信息!我还做了一个类似的测试,结果似乎表明运行100个并发线程,每次读取和验证一个XML文档,共享同一个XmlSchemaSet时都没有中断。然而,即使这样,我也不会相信它,直到MSDN明确表示它是线程安全的。拥有一个预编译的模式对象池,并为每个线程获取一个对象以供使用,并在完成后返回池,这似乎是一个好主意。文档中不再提到它了,我们应该了解它现在是线程安全的吗?