55

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.

Sylvain
  • 19,099
  • 23
  • 96
  • 145

3 Answers3

90

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:

WcfOperationContext.Current.Items["user"] = _currentUser;
var user = WcfOperationContext.Current.Items["user"] as MyUser;
Rikin Patel
  • 8,848
  • 7
  • 70
  • 78
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
1

An alternative solution without adding extra drived class.

    OperationContext operationContext = OperationContext.Current;
    operationContext.IncomingMessageProperties.Add("SessionKey", "ABCDEFG");

To get the value

var ccc = aaa.IncomingMessageProperties["SessionKey"];

That's it

ValidfroM
  • 2,626
  • 3
  • 30
  • 41
-1

I found that we miss the data or current context when we make async call with multiple thread switching. To handle such scenario you can try to use CallContext. It's supposed to be used in .NET remoting but it should also work in such scenario.

Set the data in the CallContext:

DataObject data = new DataObject() { RequestId = "1234" };
CallContext.SetData("DataSet", data);

Retrieving shared data from the CallContext:

var data = CallContext.GetData("DataSet") as DataObject;

// Shared data object has to implement ILogicalThreadAffinative

public class DataObject : ILogicalThreadAffinative
{
  public string Message { get; set; }
  public string Status { get; set; }
}

Why ILogicalThreadAffinative ?

When a remote method call is made to an object in another AppDomain,the current CallContext class generates a LogicalCallContext that travels along with the call to the remote location.

Only objects that expose the ILogicalThreadAffinative interface and are stored in the CallContext are propagated outside the AppDomain.

  • 1
    This is legacy technology, the [official documentation](https://msdn.microsoft.com/en-us/library/w61s16a1(v=vs.100).aspx) is archived and mentions this explicitly: `This topic is specific to a legacy technology that is retained for backward compatibility with existing applications and is not recommended for new development. Distributed applications should now be developed using the Windows Communication Foundation (WCF).` – MarioDS Nov 21 '16 at 11:50