Parallel Tasks and the HttpContext

A few days ago I spotted a question on StackOverflow by someone trying to use a parallel loop in an ASP.NET application. It may have been an ASP.NET MVC application (I don’t recall) but the issue is the same.

This person had some code in a parallel task that was using the HttpContext object. I would be hesitant to use that object in the first instance as I don’t know how thread safe it is. I suspect that since it holds a lot of information about the state of a request/response that it would be quite dangerous to access an instance in many threads.

His main issue what that he was getting a null back from HttpContext.Current inside the parallel tasks.

ASP.NET is already multithreaded. It abstracts most of that away so that when you are writing against it you only really ever see the request you are currently dealing with. Many other requests are happening around you, but the framework does its best to shield you from that so that you can write code cleanly. It is also its downfall in some cases.

If you don’t realise what the framework is doing for you then you could very easily fall into a number of traps when you get to the edges of that abstraction. So, when someone uses HttpContext.Current inside parallel tasks not realising that there must already by multiple requests being handled, and therefore there must be multiple simultaneous HttpContext objects floating around masquerading as the Current context. It can become very difficult to track down bugs if you know what the constraints of what Current means in this… erm… context.

Ultimately, HttpContext.Current is only available on the thread that you started with in ASP.NET. If you create new threads then it is no longer available unless you explicitly set it yourself.

9 Comments

  1. Me My Self says:

    So, what do you suggest as caching method inside an asp.net application ?

    1. Colin Mackay says:

      I’m not sure what this post has to do with caching… But there are many mechanisms built in to ASP.NET for caching and in to the .NET Framework in general. It really depends on what you want to achieve.

  2. EZ coding says:

    Actually I am using HttpContext.Current to read Session /Cache /Request collections from classes other than code behind. Never had any concurrency problems.
    Hit the first problem today while implementing parallel task that call function that internally access HttpContext.Current. Apparently it is not shared between ASP and parallel thread

    1. Colin Mackay says:

      HttpContext.Current is set at the thread level. When accessing the HttpContext.Current from classes other than the “code behind” you are still on the same thread that the request is using. As soon as you create new threads then HttpContext.Current returns the context that is current to the thread you are on. Since the parallel task is not the same thread there is no current HttpContext.

      It isn’t so much that you “lose” the HttpContext.Current on a parallel task, it is more that you never had one in the first place.

      1. neha says:

        How can I fix this? I am using Task.Factory.StartNew to calling methods in classes and populate my viewmodel. In one of the methods, I need context information as well, which is getting set to null as there is no HttpContext to that thread. How do I pass httpcontext?
        Appreciate your help

        1. As I said in the article, I wouldn’t pass the HttpContext into parallel tasks because I don’t know how thread safe it is. Having said that, if all you are going to do is read only from the HTTP Context then there is no real risk.

          If you are using Task.Factory.StartNew() to initiate the parallel task then you can pass it in to the task just like any other parameter. Something like this, perhaps:

          // Allow the current context to be used as a closure.
          HttpContext current = HttpContext.Current;
          
          // Start the task
          Task.Factory.StartNew( () => DoStuff(current));
          
          // Perform the work of the task
          public void DoStuff(HttpContext context)
          {
            // Do stuff with the context.
          }
          

          I’ve not tested this. But I imagine this would work. The reason for depositing the HttpContext.Current in a variable before starting the task is to ensure that it can be used as a closure in the lambda expression. If we didn’t do that then trying to call HttpContext.Current in the lambda expression would always return null because by that point you are in the thread created by the parallel task.

          However, as I’ve said in this post ASP.NET (MVC or WebForms) is already heavily multi-threaded so you need to ask your self is your use case sufficiently justified to launch more threads?

          1. neha says:

            Thanks alot for your answer. I understood this completely now.
            Great post!! 🙂

  3. kln says:

    Thanks for sharing!!

  4. IWC Cousteau says:

    Thanks. I hope that’s the case!

Leave a reply to EZ coding Cancel reply