Tom*_*ter 13 asp.net multithreading httpcontext
用户点击页面spawn.aspx,然后生成六个线程,渲染页面全部使用
((System.Web.IHttpHandler)instance).ProcessRequest(reference to spawn's HTTPContext);
Run Code Online (Sandbox Code Playgroud)
不要担心ASP.Net似乎正在向用户发送1个请求的响应,该部分被处理并且只发送一个响应.
问题是,在具有许多线程(quad-quads)的高流量环境(我们的生产环境)中,我们得到一个错误:
Run Code Online (Sandbox Code Playgroud)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中.我想我也想要其他部分,比如Cache.对于记录,HTTPContext.Current.Session.IsSynchronized为false.
我的问题是:
编辑:更多详细信息
所以回到这句话:"不要担心ASP.Net似乎正在向用户发送1个请求的响应,该部分被处理,只有一个响应被发送." 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);
}
Run Code Online (Sandbox Code Playgroud)
但到目前为止的所有处理 - 数据库访问,控制层次,所有这些都是并行完成的.并且它有很多 - 足够的,它仍然让它阻止渲染它的一部分将把总时间减少一半以上.
最好的部分是 - 没有必要为Excel渲染重写.所有控件都知道如何将自己渲染为excel,并且您可以独立访问每个衍生页面(实际上是'正常情况' - excel报告只是所有衍生页面的聚合.)
所以我认为最终的结果将是"你不能这样做,你需要重新思考这种方法" - 但我必须至少尝试一下,因为事实上一切都运行良好而不重复任何逻辑或任何代码或不得不抽象任何东西是如此完美.而且只有多线程就是问题,如果我按顺序渲染页面,一切都很好,只是很慢.
您的同事是对的,如果一个线程锁定资源而另一个线程尝试使用它,那么您的线程池就会繁荣!不是很好的结果。大多数人通过创建新对象并将它们传递到参数化线程来解决这个问题。如果您绝对需要使用相同的对象,那么您必须实现一些代码,首先检查该资源是否正在被另一个线程使用,然后等待一段时间,然后再次检查。一个例子是创建一个 IsInUse bool ,您总是首先检查它,然后您的线程如果正在使用该资源,则将其设置为 true ,然后在完成时将其设置为 false ,以防止其他线程尝试使用底层资源(您的 httpContext ) 。我希望这有帮助。