用户点击页面 spawn.aspx,然后生成六个线程,渲染页面全部使用
((System.Web.IHttpHandler)instance).ProcessRequest(reference to spawn's HTTPContext);
不要担心 ASP.Net 似乎向用户发送 1 个请求的 7 个响应这一事实,该部分已处理并且只发送一个响应。
问题是,在具有许多线程(quad-quads)的高流量环境(我们的生产环境)中,我们得到一个错误:
System.IndexOutOfRangeException at System.collections.ArrayList.Add at System.Web.ResponseDependencyList.AddDependencies(String[] items, String argname, Boolean cloneArray, DateTime utcDepTime) at System.Web.ResponseDependencyList.AddDependencies(String[] items, String argname, Boolean cloneArray, String requestVritualPath) at System.Web.UI.Page.AddWrappedFileDependencies(Object virtualFileDependencies) at ASP.spawned_page_no_1_aspx.FrameworkInitialize() at System.Web.UI.Page.ProcessRequest
我们不能在其他地方复制它。我的同事认为这是因为我重用了原始 HTTPContext 并将其传递给其他线程,并且它不是线程安全的。
按照这个逻辑,我尝试制作一个新的 HTTPContext 来传递给线程。但它的某些部分似乎不会“合并”。具体来说,我需要将 Session 对象放入新的 HTTPContext。我想我也想加入其他部分,比如缓存。对于记录 HTTPContext.Current.Session.IsSynchronized 是假的。
我的问题是:
- 您认为错误是由于跨线程使用 HTTPContext 造成的吗?
- 我该如何解决?
- 如果修复是为每个线程复制 HTTPContext,我怎样才能将会话(和缓存)放入新的线程中?Request 和 Response 在 ctor 中,但 Session 不可设置。
编辑:更多细节
所以回到这个声明:“不要担心 ASP.Net 似乎为 1 个请求向用户发送了 7 个响应,该部分被处理并且只发送一个响应。” Raymond Chen 的超级粉丝,我同意你的观点:“现在你有两个问题”在没有更多信息的情况下是一个合理的说法。
实际发生的是,我正在构建一个 Excel 文档以发回。在 spawn.aspx 页面中,它设置了一些状态信息,包括它正在渲染到 excel 的事实,以及要渲染到的对象。每个生成的页面都会获取该信息,并且会一直阻塞,直到轮到它们呈现给对象。如果字面上看起来像这样:
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
if (this.RenderToExcel)
{
Deadlocker.SpinUntilCurrent(DeadLockToken);
RenderReport(this, this.XLSWriter);
Deadlocker.Remove(DeadLockToken);
}
else
base.Render(writer);
}
但到那时为止的所有处理——数据库访问、控制层次结构,所有这些都是并行完成的。并且有很多 - 足以将它并行化同时仍然让它在 Render 上阻塞将把总时间减少一半以上。
最好的部分是 - 无需为 Excel 渲染重写任何内容。所有控件都知道如何将自己呈现为 excel,并且您可以独立访问每个生成的页面(这实际上是“正常情况” - excel 报告只是所有生成页面的聚合。)
所以我认为最终结果将是“你不能这样做,你需要重新考虑方法”——但我至少必须尝试一下,因为事实上一切都运行得非常好,无需复制任何逻辑或任何代码或必须抽象任何东西真是太完美了。而且只有多线程才是问题所在,如果我连续渲染页面一切都很好,只是速度很慢。