从XmlDocument对象线程读取安全吗?

我想知道我是否可以安全地从多个线程中使用SelectNodes()和SelectSingleNode()从XmlDocument对象读取而没有任何问题。 MSDN表示不保证它们是线程安全的。 如果SelectNodes()和SelectSingleNode()确实存在从多个线程运行的问题,我可以使用正确的锁定来避免任何问题吗? 我有一个WCF服务设置,需要从数据库中获取一大块xml并从这个xml中选择一些信息。 我想缓存xml以避免经常访问数据库,但我担心线程的安全性和性能。 有没有更好的方法来做这件事? 谢谢

这是交易。 如果文档说实例方法不保证线程安全,那么最好注意一下。 如果您决定在没有正确同步机制的情况下在multithreading场景中使用该类,那么您需要1)了解忽略文档的后果,并且2)为您的所有假设做好准备,以便在类的未来版本上失效。 即使对于似乎只读取内部状态的方法,此建议也是有效的。

你怎么知道SelectNodes和SelectSingleNodes不修改内部变量? 因为如果他们这样做,他们绝对不是线程安全的! 现在,我碰巧使用Reflector查看内部,我可以看到它们不会修改任何内部变量。 但是,您怎么知道未来的版本不会改变?

现在,因为我们实际上知道SelectNodes和SelectSingleNodes不修改类的内部状态,所以它们对于multithreading操作可能是安全的,尽管警告当且仅当以下条件适用时才会发出警告。

  • 在初始化XmlDocument之后,除了SelectNodes或SelectSingleNode之外没有其他方法被调用…永远。 因为我没有检查过XmlDocument类的所有方法,所以我不能说出哪些方法修改了类的内部状态,哪些方法没有。因此我会考虑除了刚才提到的2种方法之外的所有方法锁定免费使用该类的方法。
  • 在一个线程上初始化XmlDocument之后,在另一个线程上调用SelectNodes或SelectSingleNodes之前,会创建显式或隐式内存屏障。 我应该注意,由于获得multithreading环境设置,很可能会隐式创建内存屏障。 但是,我可以想到一些细微的情况,这会破坏。

我的建议……按字面意思从文档中获取警告并使用适当的同步机制。

当您要写入/读取XML文档时,如果您不想遇到竞争条件,则需要同步这两个操作。 如果你关心性能(谁没有?), ReaderWriterLockSlim可能比锁定更好。

SelectNodes / SelectSingleNode应该是安全的(它们只读取数据)。 当然,您需要将这些与实际修改xml的任何方法同步。

当你调用createInstance时,你也可以使用MsXml FreeThreadedDOMDocument模型而不是经典的DomDocument。

请注意,根据这篇文章 ,FreeThreadedDOMDocument比传统的DomDocument慢7倍或10倍。