Definitely looks like a thread contention issue since your original code has
vReader as a static variable and you have no locks around the code. Locking
the code for the entire validation period is expensive and basically loses
all the benefits of using multiple threads. The simple answer is for vReader
not to be a static member variable.
--
This posting is provided "AS IS" with no warranties, and confers no rights.
[quoted text, click to view] "Jesse Elve" <jesse.elve@t4g.com> wrote in message
news:ulRdnv6jEHA.2948@TK2MSFTNGP11.phx.gbl...
> Zafar:
>
> This has turned out to be a very interesting bug. I will be very pleased
if
> anyone will agree with me that the only possible cause is due to multiple
> threads accessing the function simultaneously. (My supervisor thinks that
> I'm jumping to this conclusion too hastily!)
>
> In any event, the exception was raised on the final line of the following
> code excerpt (!):
>
> vReader = new XmlValidatingReader(candidate);
> vReader.Schemas.Add(xsc);
> vReader.ValidationType = ValidationType.Schema;
>
> Note that this is an _exact_ excerpt. As you can see, there is _no_
> possibility that "read" is called before the "ValidationType" is set, as
the
> reader has just been instantiated 2 lines up!
>
> This becomes more interesting when the full class is considered:
>
> -------------------------------------------------------------------------
> public class OrderValidator
> {
> private static XmlValidatingReader vReader = null;
> private static XmlSchemaCollection xsc = new XmlSchemaCollection();
>
> private OrderValidator()
> {
> // Access XSD as an embedded resource in this assembly:
> System.Reflection.Assembly myAssembly;
> myAssembly = System.Reflection.Assembly.GetExecutingAssembly();
> System.Resources.ResourceManager myManager = new
> System.Resources.ResourceManager("xxx.xxx.xxx.xxx.Order_XSD",
> myAssembly);
> string xsdString =
>
myManager.GetString("Order_xsd",System.Globalization.CultureInfo.InvariantCu
> lture); // this is case-sensitive
> StringReader sr = new StringReader(xsdString);
> XmlTextReader schemaReader = new XmlTextReader(sr);
>
> // Add XSD to schemaCollection
> xsc.Add(null, schemaReader);
> }
>
> /// <summary>
> /// Singleton instance via .NET-Framework-managed singleton semantics
> /// </summary>
> public static readonly OrderValidator Instance = new OrderValidator();
>
> /// <summary>
> /// Validation method
> /// </summary>
> /// <param name="candidate">fresh XMLTextReader (unread!)</param>
> /// <returns>true for valid XML or throws an exception for
> failure</returns>
> public Boolean Validates(XmlTextReader candidate)
> {
> Boolean isValid = false;
> vReader = new XmlValidatingReader(candidate);
> vReader.Schemas.Add(xsc);
> vReader.ValidationType = ValidationType.Schema;
> try
> {
> while (vReader.Read()){}
> isValid = true;
> }
> catch(Exception e)
> {
> string message = "Validation failed: ";
> message += "Element name: " + (vReader.Name != null ? vReader.Name :
> String.Empty) + ". ";
> message += "Element value: " + (vReader.Value != null ? vReader.Value
:
> String.Empty) + ". ";
> throw(new ApplicationException(message, e));
> }
> return isValid;
> }
>
> }
> -------------------------------------------------------------------------
>
> There were numerous factors which made it logical to design this class as
a
> Singleton, chiefly the size and complexity of the XSD. Once instantiated,
> the singleton instance of this class does service validation requests from
> multiple threads.
>
> The only explanation that I can come up with is that 2 contending threads
> are in the "Validates" method simultaneously. I'm very open to any other
> explanation!
>
> In the meantime, I have already implemented the following modifications
> based on my "thread contention" theory:
>
> --------------------------------------------------------------------------
>
> // object used for method-level locking
> private static Object privateStaticObject = new Object();
>
> public Boolean Validates(XmlTextReader candidate)
> {
> Boolean isValid = false;
> lock (privateStaticObject)
> {
> vReader = new XmlValidatingReader(candidate);
> vReader.Schemas.Add(xsc);
> vReader.ValidationType = ValidationType.Schema;
> try
> {
> while (vReader.Read()){}
> isValid = true;
> }
> catch(Exception e)
> {
> string message = "Validation failed: ";
> message += "Element name: " + (vReader.Name != null ? vReader.Name :
> String.Empty) + ". ";
> message += "Element value: " + (vReader.Value != null ? vReader.Value
:
> String.Empty) + ". ";
> throw(new ApplicationException(message, e));
> }
> }
> return isValid;
> }
>
> --------------------------------------------------------------------------
>
> Based on a previous incident, however, our architect thinks I'm too quick
to
> jump to a "thread contention" conclusion. If anyone has any other
> interpretations or suggestions please let me know!
>
>