我加载并执行我的.cshtml文件,如下所示
var webPage = WebPage.CreateInstanceFromVirtualPath(_relativeFilePath);
var httpContext = new HttpContextWrapper(HttpContext.Current);
var startPage = StartPage.GetStartPage(webPage, "_PageStart", new[] { "cshtml" });
var pageContext = new WebPageContext(httpContext, webPage, startPage);
var sb = new StringBuilder();
using (var writer = new StringWriter(sb))
{
webPage.ExecutePageHierarchy(pageContext, writer);
}
string output = sb.ToString().Trim();
现在,由于(在我的世界中),每个.cshtml文件都是一个独立的单元,我可以让上面的代码并行运行N次,但在极少数情况下,它会崩溃,出现下面的异常。
System.InvalidOperationException: Stack empty.
at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
at System.Collections.Generic.Stack`1.Pop()
at System.Web.WebPages.TemplateStack.Pop(HttpContextBase httpContext)
at System.Web.WebPages.WebPageBase.ExecutePageHierarchy()
at System.Web.WebPages.WebPage.ExecutePageHierarchy(IEnumerable`1 executors)
at System.Web.WebPages.WebPage.ExecutePageHierarchy()
at System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage)
如果禁用并行化并逐个运行所有.cshtml文件,则无法触发异常。这让我想知道是否WebPages的一些内部工作方式不是线程安全的,每个对ExecutePageHierarchy
的调用都以某种方式访问当前HttpContext
中的一些非唯一值
发布于 2012-03-23 17:30:05
对于多个使用者来说,HttpContext和其他ASP.NET内部对象通常不是线程安全的。如果你的目标仅仅是使用Razor模板引擎来并行处理多件事情,我相信你可以做到,因为Razor本身并不直接依赖于ASP.NET中的任何东西。但是一旦你涉及到.cshtml (System.Web.WebPages),不幸的是你在这一点上会受到ASP.Net的内部特性的限制。
发布于 2012-08-30 06:00:45
只是为了让其他人看到这个帖子。我实现了抽象类HttpContextBase和HttpRequestBase的最小实现。然后,当我想呈现viewPage时,我会提供这些类的新实例,而不是真正的实例。(我没有使用模板框架的原因是我还没有找到一个线程安全的框架,提示一下谁?)
public class MockRequest : HttpRequestBase
{
public override bool IsLocal { get { return false; } }
}
public class MockHttpContext : HttpContextBase
{
private readonly IDictionary _items = new Hashtable();
public override HttpRequestBase Request { get { return new MockRequest(); } }
public override IDictionary Items { get { return _items; } }
}
https://stackoverflow.com/questions/9740467
复制