C#非调试模式运行加载XSL时报操作超时问题咨询
问题现象
- 带断点的调试模式下程序可正常运行
- 非调试模式直接启动时,始终抛出错误
The operation has timed out - 最初错误触发点在自行编写的HTTP请求代码行,更新代码后错误触发位置发生变化
报错堆栈
at System.Net.HttpWebRequest.GetResponse() at System.Xml.XmlDownloadManager.GetNonFileStream(Uri uri, ICredentials credentials, IWebProxy proxy, RequestCachePolicy cachePolicy) at System.Xml.XmlDownloadManager.GetStream(Uri uri, ICredentials credentials, IWebProxy proxy, RequestCachePolicy cachePolicy) at System.Xml.XmlUrlResolver.GetEntity(Uri absoluteUri, String role, Type ofObjectToReturn) at System.Xml.XmlTextReaderImpl.OpenUrl() at System.Xml.XmlTextReaderImpl.Read() at System.Xml.XPath.XPathDocument.LoadFromReader(XmlReader reader, XmlSpace space) at System.Xml.XPath.XPathDocument..ctor(XmlReader reader, XmlSpace space) at System.Xml.Xsl.XsltOld.Compiler.LoadDocument(XmlTextReaderImpl reader) at System.Xml.Xsl.XslTransform.Load(String url) at eNotasGW.DFe.Crawler.Application.Abaco.Crawling.Base.AbacoWSCrawlerBaseV2.<GetRangeItemsAsync>d__17.MoveNext() in C:\tfs\Trunk\eNotasGW.DFe.Crawler\eNotasGW.DFe.Crawler.Application.Abaco\Crawling\Base\AbacoWSCrawlerBaseV2.cs:line 225 at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at eNotasGW.DFe.Crawler.Application.Abaco.Crawling.V2.AbacoDFePrestadaCrawlerV2.<ExecuteCoreAsync>d__1.MoveNext() in C:\tfs\Trunk\eNotasGW.DFe.Crawler\eNotasGW.DFe.Crawler.Application.Abaco\Crawling\V2\AbacoDFePrestadaCrawlerV2.cs:line 24 at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at eNotasGW.DFe.Crawler.Application.Commom.CrawlerBase.<ExecuteAsync>d__4.MoveNext() in C:\tfs\Trunk\eNotasGW.DFe.Crawler\eNotasGW.DFe.Crawler.Application.Commom\Services\Base\CrawlerBase.cs:line 29 at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at eNotasGW.DFe.Crawler.Application.Commom.Web.WebCrawlerBase.<ExecuteAsync>d__19.MoveNext() in C:\tfs\Trunk\eNotasGW.DFe.Crawler\eNotasGW.DFe.Crawler.Application.Commom\Web\WebCrawlerBase.cs:line 45 at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at eNotasGW.DFe.Crawler.Application.Commom.Web.PreAuthenticatedWSCrawlerBase.<ExecuteAsync>d__3.MoveNext() in C:\tfs\Trunk\eNotasGW.DFe.Crawler\eNotasGW.DFe.Crawler.Application.Commom\Web\PreAuthenticatedWSCrawlerBase.cs:line 75
报错位置对应代码
报错点位于AbacoWSCrawlerBaseV2.cs第225行,代码逻辑为通过xslTransform加载远程XSL资源:
var xslTransform = new XslTransform(); var pdfResponseLink = new Uri(BaseUri, Url.Combine(RelativePath, "../schemas/nfse/nfse_v204.xsl")); xslTransform.Load(pdfResponseLink.ToString());
问题原因
- 你调用的
XslTransform.Load(string url)重载,会在方法内部隐式发起独立的HTTP请求拉取远程XSL资源,这个内部请求不会继承你业务代码里配置的认证凭证、代理规则、超时参数,且使用框架默认的极短超时配置。 - 调试模式下,断点停留会给网络请求留出充足的缓冲时间,同时调试状态下.NET网络请求的超时判定阈值比Release非调试模式更宽松,因此不会触发超时;非调试模式下程序执行速度快,隐式发起的HTTP请求来不及在默认超时窗口内完成资源拉取,就会抛出超时错误。
- 之前报错出现在你自己编写的HTTP请求代码行,是因为当时那段请求本身存在配置问题,调整代码修复该问题后,才暴露出
XslTransform.Load内部隐式请求的超时缺陷,因此报错位置发生了变化。
修复建议
- 不要直接把远程URL传入
XslTransform.Load方法。先用你自己配置好超时、认证、代理规则的HTTP客户端把XSL资源拉取到本地内存流,再调用XslTransform.Load接收流的重载方法完成加载,把网络请求的控制权收回到业务代码中,统一配置参数。 - 如果该XSL是不会频繁变动的静态资源,直接将文件嵌入程序集或存储到本地文件系统,不要每次运行都从远程拉取,从根源上规避网络请求带来的超时问题。
内容的提问来源于stack exchange,提问作者Thiago
相关产品推荐
相关产品推荐

