.NET代码无法捕获System.Xml.Xsl.XslLoadException致IIS崩溃
无法捕获XslCompiledTransform加载错误XSLT时抛出的XslLoadException异常
加载存在错误的XSLT样式表时,即便用try { } catch(Exception unhandled) { }包裹代码,也无法捕获XslCompiledTransform抛出的异常,最终导致w3wp.exe崩溃。当前场景是引用的样式表存在重复模板函数,需要明确为何C#代码处理不了System.Xml.Xsl.XslLoadException异常。
调试获取的错误信息
System.Xml.Xsl.XslLoadException HResult=0x80131942 Message='helper.name' is a duplicate template name. Source=FLX StackTrace: at ProjectFlx.FlxTemplater.LoadTransformation(XslCompiledTransform xslt) in D:\GitHub\ProjFlx\Src\TMPLTSite\WebTemplater.cs:line 475 at ProjectFlx.FlxTemplater.<>c__DisplayClass38_0.<ProcessTemplate>b__0() in D:\GitHub\ProjFlx\Src\TMPLTSite\WebTemplater.cs:line 429 at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart() This exception was originally thrown at this call stack: [External Code] ProjectFlx.FlxTemplater.LoadTransformation(System.Xml.Xsl.XslCompiledTransform) in WebTemplater.cs ProjectFlx.FlxTemplater.ProcessTemplate.AnonymousMethod__0() in WebTemplater.cs [External Code]
调用代码
注:因XML和XSL复杂度高、体积大,需要增大转换栈大小,所以用了线程匿名调用。
try { var xslt = new XslCompiledTransform(); //xslt = LoadTransformation(xslt); System.Threading.Thread t = new System.Threading.Thread(() => xslt = LoadTransformation(xslt), 8 * 1024 * 1024); t.Start(); t.Join(); XsltArgumentList xsltparms = DicToXsltParms(); using (var mem = new MemoryStream()) { _xml.Save(mem); mem.Flush(); mem.Seek(0, SeekOrigin.Begin); var readersettings = new XmlReaderSettings(); var reader = XmlReader.Create(mem, readersettings); using (_writer = new StringWriter()) { xslt.Transform(reader, xsltparms, _writer); } } } catch(System.Xml.Xsl.XsltCompileException handled) { System.Diagnostics.Debug.WriteLine("Caught XsltCompileException"); System.Diagnostics.Debug.WriteLine(handled.Message); } //catch(System.Xml.Xsl.XslLoadException handled) //{ //} catch (Exception unhandled) { var ex = new Exception("Failed to Transform xml/xslt", unhandled); ex.Source = "ProjectFlx.FlxTemplater.ProcessTemplate"; throw ex; }
问题原因及解决方案
核心原因
异常在新建的子线程中抛出,外层try/catch仅能捕获当前主线程的异常,无法捕获子线程的未处理异常。子线程的执行上下文独立于主线程,未处理异常会直接导致进程崩溃。
修复方案
- 将异常捕获逻辑移到子线程内部,确保捕获子线程中
LoadTransformation抛出的异常:
// 定义共享变量存储异常信息 private Exception _loadException; // 修改线程创建逻辑 System.Threading.Thread t = new System.Threading.Thread(() => { try { xslt = LoadTransformation(xslt); } catch(XslLoadException ex) { System.Diagnostics.Debug.WriteLine($"XSL加载失败:{ex.Message}"); _loadException = ex; } catch(Exception ex) { System.Diagnostics.Debug.WriteLine($"线程执行异常:{ex.Message}"); _loadException = ex; } }, 8 * 1024 * 1024);
- 主线程等待子线程结束后检查异常状态,根据结果决定后续流程:
t.Start(); t.Join(); // 检查子线程是否抛出异常 if(_loadException != null) { throw new Exception("XSL样式表加载失败", _loadException); } // 后续转换逻辑继续执行...
- 启用XslLoadException的捕获分支,在主线程中针对性处理该异常类型,避免遗漏:
catch(System.Xml.Xsl.XslLoadException handled) { System.Diagnostics.Debug.WriteLine("Caught XslLoadException"); System.Diagnostics.Debug.WriteLine(handled.Message); // 这里可以添加友好提示、日志记录等逻辑 }
内容的提问来源于stack exchange,提问作者kstubs
相关产品推荐
相关产品推荐

