我尝试在多线程应用程序中验证xml文件,但我遇到了问题(验证错误:未声明''元素。)如果我运行单个线程的代码,或者一次只有一个xml文件,一切都按预期工作。
我认为它与此Schema validation error / Thread safety of XmlSchemaSet?问题中的问题相同,但我无法弄清楚如何使其发挥作用。
我最初使用的内联架构虽然很好,但是解析外部文件的速度太慢了。我决定在ConcurrentDictionary中缓存模式以加快速度。
以下是代码:
此方法属于每个线程的本地对象。
public void validate()
{
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
//settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
//settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
settings.ValidationEventHandler +=
new ValidationEventHandler(ValidationCallBack);
using (var tr = new XmlTextReader(xmlFile))
{
tr.MoveToContent();
var url = tr.GetAttribute("xsi:noNamespaceSchemaLocation");
var schema = SchemaFactory.GetSchema(url);
settings.Schemas.Add(schema);
}
using (XmlReader reader = XmlReader.Create(xmlFile, settings))
{
while (reader.Read());
}
SchemaFactory定义:
public static class SchemaFactory
{
static ConcurrentDictionary<string, XmlSchema> schemaStore =
new ConcurrentDictionary<string, XmlSchema>();
public static XmlSchema GetSchema(string url)
{
XmlSchema schema = null;
if (!schemaStore.TryGetValue(url, out schema))
{
var schemadata = new System.Net.WebClient().DownloadString(url);
schema = XmlSchema.Read(new StringReader(schemadata), (sender, args) => { });
schemaStore.TryAdd(url, schema);
}
return schema;
}
}
在多个线程中处理时,如何在xml文件中第一次遇到时实时向缓存添加架构?
答案 0 :(得分:2)
XML Schema不是线程安全的。将模式缓存为字符串,然后它可以工作:
class Program
{
private ConcurrentDictionary<string, string> schemaStore =
new ConcurrentDictionary<string, string>();
static void Main(string[] args)
{
Program p = new Program();
for (int i = 0; i < 40;i++ )
new Thread(new ThreadStart(p.validate)).Start();
Console.ReadKey();
}
public void validate()
{
string xmlFile = "XMLFile1.xml";
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
//settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
//settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
settings.ValidationEventHandler +=
new ValidationEventHandler(ValidationCallBack);
using (var tr = new XmlTextReader(xmlFile))
{
tr.MoveToContent();
var url = tr.GetAttribute("xsi:noNamespaceSchemaLocation");
string schemaXml =null;
if (!schemaStore.TryGetValue(url, out schemaXml))
{
//Console.WriteLine("Need download");
using (System.Net.WebClient wc = new System.Net.WebClient())
{
string schemadata = wc.DownloadString(url);
schemaStore.TryAdd(url, schemadata);
schemaXml = schemadata;
}
}else
{
//Console.WriteLine("Cache hit");
}
XmlSchema schema = XmlSchema.Read(new StringReader(schemaXml), (sender, args) => { });
settings.Schemas.Add(schema);
}
using (XmlReader reader = XmlReader.Create(xmlFile, settings))
{
while (reader.Read()) ;
}
Console.WriteLine("Thread "+Thread.CurrentThread.ManagedThreadId+" completes");
}
private void ValidationCallBack(object sender, ValidationEventArgs args)
{
if (args.Severity == XmlSeverityType.Error)
Console.WriteLine("Thread " + Thread.CurrentThread.ManagedThreadId + " -> Error: " + args.Message);
else
Console.WriteLine("Thread " + Thread.CurrentThread.ManagedThreadId + " -> Warning: " + args.Message);
}
}
答案 1 :(得分:-2)
如果Schema validation error / Thread safety of XmlSchemaSet?中所述仍然无法对同一编译模式运行多个并行模式验证,那么解决方法可能是使用没有的Saxon模式验证器[无耻插件]这个限制。