Beware of using the ThreadStaticAttribute in an ASP.NET environment

While implementing NAuthorize, I needed an object registry on a per user/session basis as discussed in

Patterns of Enterprise Application Architecture

The way this works in .NET is as follows (assuming ObjectRegistry is a collection class and a singleton):

    [ThreadStatic]
private static volatile ObjectRegistry _instance = null;

public static ObjectRegistry Instance
{
get
{
if(_instance == null)
{
lock(typeof(ObjectRegistry))
{
if(_instance == null)
{
_instance = new ObjectRegistry();
}
}
}
return(_instance);
}
}


The ThreadStatic attribute is what makes this work. The only gotcha so far is that this doesn't work in an ASP.NET application (Web/Webservice) as threads are reused for different requests, hence having the wrong ObjectRegistry serving the wrong user/session. The only solution I can think of for the time being, is having the ObjectRegistry detect if there's a HttpContext, and if so, subscribe to the EndRequest event of the associated HttpApplication and clear itself when the event fires.

UPDATE: Create your own HttpContext class from Brian Bilbro also provides a solution to this same problem. The only thing worth checking out is that the CallContext is properly destroyed when the web/webservice request is served.

Published 19 March 2003 10:02 PM by yreynhout
Filed under: ,

Comments

# Justin Rudd said on 19 March, 2003 07:36 AM
EndRequest is the end of the request, not the end of the session. If you want the end of the session, in your global.asax (I can't remember what the corresponding event in code would be), you can add a Session_OnEnd which will get fired when the session ends.
# Yves Reynhout said on 19 March, 2003 07:58 AM
I'm afraid you've missed the point. I don't want to capture the end of a session, but the end of the current request. ASP.NET reuses its threads to serve different request related to potentially different sessions. I cannot trust ASP.NET to execute every request related to a certain session to execute on the same thread (and IMHO, ASP.NET's current behavior is as it should be).
# TrackBack said on 19 March, 2003 04:02 PM
Per Session Static Variables : Jesse Ezell Blog
# TrackBack said on 19 March, 2003 04:02 PM
Yves Reynhout's Blog
# Guy Murphy said on 09 April, 2003 08:24 PM
Firstly if I'm missing your point I apologise, it's easy not to see the point being pressed when skimming a web page.

Two choices.

1) Use request handlers that aren't reusable...

See the "IsReusable" property of the IHttpHandler interface.

2) Use thread safe singletons...

public sealed class OccurenceComparer: IComparer {

private static volatile OccurenceComparer _instance = null;
private static object _syncRoot = new object();

public static OccurenceComparer Instance {
get {
// if singleton hasn't been instanciated, create one
if (_instance == null) {
lock (_syncRoot) {
if (_instance == null) { // deliberate double check after lock in place
_instance = new OccurenceComparer();
}
}
}
return _instance;
}
}

private OccurenceComparer () {}

public int Compare (object obj1, object obj2) {
...
}
}
# kulki said on 24 January, 2004 03:24 AM
I was trying out the link provided by Brian Bilbro, but it still dosent seem to be working. Am I the only one?
# kulki said on 24 January, 2004 03:27 AM
Is it possible for me take a look at the code where you implement ObjectRegistry. I am looking to implement the same!
thanks
# TrackBack said on 24 January, 2004 12:50 PM
# Basuki Sugiarto said on 27 May, 2004 07:49 PM
Great subject, but just wondering if we can add a method inside the singleton to nullify the instance. Then in ASP.NET Global.asax, you call that method at the Application_EndRequest?

Just a thought!
# Alex said on 26 August, 2008 05:05 PM

I am a little bit puzzeled as to why you have to do a lock on the object if the static instance is declared as ThreadStatic, and therefore is not shered between threads.

# DotNetKicks.com said on 04 September, 2008 07:29 PM

You've been kicked (a good thing) - Trackback from DotNetKicks.com

# wekempf said on 05 September, 2008 01:23 PM

I'm not going to address the problem you think exists here.  Let others do that.  But I want to point out your code has several glaring problems.

1.  You should never lock a Type object.  (msdn.microsoft.com/.../1c9txz50.aspx).

2.  The DCL (double-checked lock) pattern is dangerous and rarely needed on .NET.  On many platforms, DCL is broken.  The .NET VM actually provides for properly using the DCL regardless of the platform the byte code is eventually compiled on, but it requires the use of "volatile" or "MemoryBarrier", which you've not done.  For a singleton, however, you can and should just rely on the language semantics of static constructors and not use the DCL (of course, in this case it's not a traditional singleton, but see the next point). (blogs.msdn.com/.../volatile-and-memorybarrier.aspx)

3.  In this case, the DCL isn't needed.  "_instance" is "ThreadStatic" and can't be accessed by other threads. No synchronization is required for the initialization code.

# deostroll said on 15 January, 2009 12:11 PM

Create your own HttpContext class from Brian Bilbro --> the site throws an error. Evidently not your problem, but any similar article out there...?

Leave a Comment

(required) 
(required) 
(optional)
(required)