7

I'm using a library that relies on HttpContext.Current. The library is Facebook C# SDK, but my question should apply in other scenarios as well. I'd like to use this library from inside of a parallel thread. However, HttpContext.Current is not available in the parallel thread, so I'm thinking about caching it to a local variable and then setting it in the parallel thread like this:

var httpContext = HttpContext.Current;
Parallel.ForEach(items, item => {

    try {

        HttpContext.Current = httpContext;

        // Call a method that relies on HttpContext.Current

    } finally {
        HttpContext.Current = null;
    }
});

Do you foresee anything wrong with this? Are there any repercussions to doing this?

Johnny Oshika
  • 54,741
  • 40
  • 181
  • 275
  • What exactly are you using from the httpContext? If it's just a value from the cache for example it would be better to pass that into each thread. – Kevin Holditch Oct 21 '11 at 15:20
  • Open it up in Reflector or ILSpy. Observe the `Current` boiling down to `Thread.CurrentThread.GetIllogicalCallContext().HostContext`. The answer becomes obvious :) – Ilia G Oct 21 '11 at 15:20
  • 3
    Why not just pass the context in as state? Much cleaner – Marc Gravell Oct 21 '11 at 15:24
  • I just peaked into the Facebook C# SDK code, and it look like it only uses HttpContext.Current to determine whether the current request is secure or not (_httpContext.Request.Url.Scheme). So my example code above does work, but maybe not a good idea? – Johnny Oshika Oct 21 '11 at 15:43
  • Kevin and Marc, can you provide an example of your suggested ideas? I'd prefer not to change the library code though. Thanks. – Johnny Oshika Oct 21 '11 at 15:44
  • I am facing the same question, except that I have code in business layers that need to get access to "singletons" that are only valid within the current http context. I wonder if it's really a good idea to set that HttpContext.Current to null at the end without some additional checks. Does the Parallel.ForEach run the code only on additional threads, or does it also use the current thread? If it also uses the current thread, you might be clearing it on the actual request thread? – Dan C Oct 24 '11 at 22:42
  • Good question, Dan. I'm not 100% certain. I thought Parallel.ForEach grabbed a new thread from the thread pool, but I wonder if there are scenarios where the current thread is used? – Johnny Oshika May 02 '12 at 14:36
  • Related question http://stackoverflow.com/questions/3790817/c-adding-context-to-parallel-foreach-in-asp-net – Michael Freidgeim Jun 13 '12 at 17:47
  • @MarcGravell How to cleanly send context as state? As a parameter, [it throws exception](http://stackoverflow.com/q/1723919/2404470). What is the right way? – Zameer Ansari Feb 18 '16 at 11:09

1 Answers1

4

For me seems ok. The use of try ... finally is a good point too because thread can be reused and you can keep the context alive for long times, avoiding garbage collection. Don't think there is another way to solve this.

Be careful however that the api you are calling does not create problems in this multithreading environment. Not all code is thread safe performing write operations or read operations that involve writing\reading some cached value.

Be careful also that field values can not be propagated correctly and\or in time from one thread to another if they are not volatile or if System.Threading.Interlocked is not used! This may create you problems, especially in release builds.

You can however use Thread.MemoryBarrier or lock, search on the web for this annoying (but inevitable) issue.

Salvatore Previti
  • 8,956
  • 31
  • 37