Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
395 views
in Technique[技术] by (71.8m points)

asp.net - Using an HTTPContext across threads

User hits page spawn.aspx which then spawns a half-dozen threads, rendering pages all using

 ((System.Web.IHttpHandler)instance).ProcessRequest(reference to spawn's HTTPContext);

Don't worry about the fact that ASP.Net is seemingly sending the user 7 responses for 1 request, that part is handled and only one response gets sent.

The problem is, in a high-traffic enviroment (our Production enviroment) with many threads (quad-quads) we get an error:

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

We can't duplicate it elsewhere. My coworker believes this is because I'm reusing the original HTTPContext and passing it into the other threads, and that it's not Thread-Safe.

Following this logic, I've tried making a new HTTPContext to pass into the threads. But parts of it seemingly won't "combine". Specifically, I need to get the Session object into the new HTTPContext. I imagine I'd want to get other parts in as well, like Cache. For the record HTTPContext.Current.Session.IsSynchronized is false.

My questions are:

  1. Do you think the error is from using HTTPContext across threads?
  2. How can I fix it?
  3. If the fix is duplicating the HTTPContext for each thread, how can I get the Session (and Cache) into the new one? Request and Response come in the ctor, but Session is not settable.

Edit: More Details

So going back to this statement: "Don't worry about the fact that ASP.Net is seemingly sending the user 7 responses for 1 request, that part is handled and only one response gets sent." Huge fan of Raymond Chen, I agree with you: "Now you have two problems" is a reasonable statement in the absence of any more information.

What's actually happening is that I'm building an Excel Document to send back. In the spawn.aspx page it's setting up some state information, including the fact that it's rendering to excel, and the object to do the rendering to. Each spawned page gets that information, and will block until it's their turn to render to the object. If literally looks like this:

 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);
 }

But all the processing up to that point - database access, control heirarchy, all that's done in parallel. And there's a lot of it - enough that parrallizing it while still letting it block on Render will cut the overall time in over half.

And the best part of it is - nothing had to be rewritten for the Excel render. All the controls know how to render themselves to excel, and you can visit each spawned page independently (that's the 'normal case' actually - the excel report is just an aggregation of all the spawned pages.)

So I figured the end result was going to be "you can't do this, you need to rethink the approach" - but I had to at least try, because the fact that everything works so nicely without duplicating any logic or any code or having to abstract anything is just so perfect. And it's only multi-threading that's the problem, if I render the pages serially everything is fine, just slow.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Whilst the HttpContext is designed to handle a context that isn't thread specific (because the http context can start on one thread and finish on another), it isn't implicitly thread safe.

Essentially the problem is you are doing something that isn't intended, these requests would be multiple generally and each have their own assigned HttpApplication to fulfill the request, and each have their own HttpContext.

I really would try and let the asp.net infrastructure delegate the requests itself.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...