在哪里存储当前WCF呼叫的数据? ThreadStatic安全吗?

时间:2009-12-13 06:22:16

标签: wcf

当我的服务执行时,许多类需要访问User.Current(这是我自己的User类)。我可以安全地将_currentUser存储在[ThreadStatic]变量中吗? WCF是否重用其线程?如果是这种情况,它什么时候会清理ThreadStatic数据?如果使用ThreadStatic不安全,我应该把数据放在哪里?在OperationContext.Current中是否有一个可以存储这种数据的地方?

编辑12/14/2009:我可以断言使用ThreadStatic变量并不安全。 WCF线程在线程池中,而ThreadStatic变量从不重新初始化。

3 个答案:

答案 0 :(得分:84)

有一个博客post建议实施IExtension<T>。您也可以查看此discussion

以下是建议的实施方案:

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) { }
}

你可以这样使用:

WcfOperationContext.Current.Items["user"] = _currentUser;
var user = WcfOperationContext.Current.Items["user"] as MyUser;

答案 1 :(得分:0)

不添加额外的驱动类的替代解决方案。

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

获得价值

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

就这样

答案 2 :(得分:-1)

我发现当我们使用多线程切换进行异步调用时,我们会错过数据或当前上下文。要处理这种情况,您可以尝试使用CallContext。它应该用于.NET远程处理,但它也应该适用于这种情况。

在CallContext中设置数据:

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

从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; }
}

为什么选择ILogicalThreadAffinative?

当对另一个AppDomain中的对象进行远程方法调用时,当前的CallContext类会生成一个LogicalCallContext,它随着对远程位置的调用而移动。

只有公开ILogicalThreadAffinative接口并存储在CallContext中的对象才会传播到AppDomain之外。