0

According to MSDN, XmlSchemaSet class is not guaranteed to be thread-safe.

So can multiple XmlReader objects be created with a single XmlReaderSettings object referencing one XmlSchemaSet object and used concurrently from multiple threads? Or does this mean I am required to create a new XmlReaderSettings object and assign it a new copy of XmlSchemaSet every time I need to process a new document in the background?

Seems like this would be very wasteful. Especially since XmlSchemaSet would need to recompile the schema for every new document.

Is the answer the same for XmlWriter objects?

Of course, I wouldn't modify the XmlSchemaSet object after populating it initially. I would also call the Compile method before first using it. After that, it seems like everything should be just safe since only reads would be performed, but I'm not sure.

relatively_random
  • 4,505
  • 1
  • 26
  • 48
  • @ mjwills Sorry, I was away from the computer. Yes, both answers confirm what I was afraid of: don't rely on this, even though probably multi-reader, zero-writer scenarios could work. Now to decide which one to mark as accepted... – relatively_random Aug 16 '17 at 06:57

2 Answers2

2

If it says it isn't thread-safe, then (contractually) you can't share it / use it concurrently.

Now it might work. But Microsoft are explicitly stating that it isn't guaranteed to work. So even if it works today, if may not work the next time you upgrade .NET Framework (for example).

The usage of other types that aren't thread-safe at http://referencesource.microsoft.com/#System.Xml/System/Xml/Schema/XmlSchemaSet.cs (e.g. Hashtable) would mean I would strongly encourage you not to use XmlSchemaSet across threads. Using XmlSchemaSet across multiple threads may be OK if you are just reading (since Hashtable supports multiple readers, for example) - but XmlSchemaSet working across multiple threads isn't guaranteed for perpetuity (even if it does work today).

mjwills
  • 23,389
  • 6
  • 40
  • 63
2

Not 100% sure about current versions, but in the beginnings of .NET I ran into this issue. Compiling a XmlSchema most likely modifies it (adding post-compilation information to it). Validating against one that already is compiled most likely does not, but the point is: you cannot rely on this.

My way of dealing with it ever since is (as an alternative to creating new schemas all the time) to keep a singleton inside a class and synchronize access to it. Which means: never handing out a reference to it directly or indirectly (e.g. through an XmlReader).

Usually I write static service methods to load an XML into an XDocument or similar.

tinudu
  • 1,139
  • 1
  • 10
  • 20
  • I know compiling mutates the state, which is why I stated I'd compile before passing the schema set to any other thread. I don't understand how your proposal would avoid the issue, though. The singleton or static class would still either have to create a copy of the XmlSchemaSet and recompile it for each call, or synchronise access between threads. So you either add extra computation or lose concurrency, which is the whole point of using multiple threads. – relatively_random Aug 16 '17 at 07:09
  • 1
    I meant: syncronizing access and losing concurrency for the matter of XML parsing, but of course not for subsequent processing of a materialized e.g. `XDocument`. – tinudu Aug 16 '17 at 10:25