tags:

views:

200

answers:

2

While my service executes, many classes will need to access User.Current (that is my own User class). Can I safely store _currentUser in a [ThreadStatic] variable? Does WCF reuse its threads? If that is the case, when will it clean-up the ThreadStatic data? If using ThreadStatic is not safe, where should I put that data? Is there a place inside OperationContext.Current where I can store that kind of data?

Edit 12/14/2009: I can assert that using a ThreadStatic variable is not safe. WCF threads are in a thread pool and the ThreadStatic variable are never reinitialized.

+3  A: 

There's a blog post which suggests implementing an IExtension<T>. You may also take a look at this discussion.

Here's a suggested implementation:

public class WcfOperationContext : IExtension<OperationContext>
{
    private readonly IDictionary<string, object> items;

    private WcfOperationContext()
    {
        items = new Dictionary<string, object>();
    }

    public IDictionary<string, object> Items
    {
        get { return items; }
    }

    public static WcfOperationContext Current
    {
        get
        {
            WcfOperationContext context = OperationContext.Current.Extensions.Find<WcfOperationContext>();
            if (context == null)
            {
                context = new WcfOperationContext();
                OperationContext.Current.Extensions.Add(context);
            }
            return context;
        }
    }

    public void Attach(OperationContext owner) { }
    public void Detach(OperationContext owner) { }
}

Which you could use like that:

WcfInstanceContext.Current.Items["user"] = _currentUser;
var user = WcfInstanceContext.Current.Items["user"] as MyUser;
Darin Dimitrov
Thanks, I'll explore that option.
Sly
@Darin: check the other answer I provided, what do you think of that?
Sly
A: 

I found another solution. You can use the OperationCompleted event of the OperationContext class to clear your ThreadStatic variables.

public class SomeClass
{
    [ThreadStatic]
    private static _currentUser = null;

    public static void GetUser()
    {
        if ( _currentUser == null )
        {
            _currentUser = LoadUser();

            // Reinitialize _currentUser at the end of the request
            OperationContext.Current.OperationCompleted +=
                (sender, args) => _currentUser = null;
        }

        return _currentUser;
    }
}
Sly
I accepted this answer because it is the simplest solution. Darin's solution is more sophisticated and might me better in more complex scenarios.
Sly