寻求一个尺寸适合所有基于上下文的存储

时间:2009-04-09 20:19:32

标签: c# .net httpcontext thread-static

首先,我希望基于上下文的存储在整个框架中保持一致!

话虽如此,我正在寻找一种优雅的解决方案,使这些属性在ASP.NET,WCF和任何其他多线程.NET代码中都是安全的。这些属性位于一些低级跟踪帮助程序中(如果您想知道它们为什么是内部的,可以通过方法公开这些属性。)

我宁愿不依赖于不需要的程序集(如System.Web等)。我不想要求使用此代码的任何人配置任何东西。我只是想让它起作用;)虽然这可能太高了......但

任何人都有任何诡计? (我见过Spring的实现)

    internal static string CurrentInstance
    {
        get
        {
            return CallContext.LogicalGetData(currentInstanceSlotName) as string;
        }
        set
        {
            CallContext.LogicalSetData(currentInstanceSlotName, value);
        }
    }

    internal static Stack<ActivityState> AmbientActivityId
    {
        get
        {
            Stack<ActivityState> stack = CallContext.LogicalGetData(ambientActivityStateSlotName) as Stack<ActivityState>;
            if (stack == null)
            {
                stack = new Stack<ActivityState>();
                CallContext.LogicalSetData(ambientActivityStateSlotName, stack);
            }

            return stack;
        }
    }

更新

安全我并不是指同步。有关问题的背景here

2 个答案:

答案 0 :(得分:2)

这是NHibernate的“上下文”实现(至少部分)的链接:

https://nhibernate.svn.sourceforge.net/svnroot/nhibernate/trunk/nhibernate/src/NHibernate/Context/

在NHibernate的背景下,我不清楚它在何处或如何发挥作用。也就是说,如果我想在“上下文”中存储一些值,我会从NHibernate获取“上下文”并添加我的值吗?我不使用NHibernate,所以我真的不知道。

我想你可以自己查看并确定这种实现是否对你有用。显然,想法是注入所需的实现,具体取决于应用程序的类型(ASP.NET,WCF等)。这可能意味着一些配置(如果使用MEF加载“ICurrentSessionContext接口”,可能是最小的。)

无论如何,当我在前一段时间找到CallContext.SetData/GetData/LogicalSetData/LogicalGetDataThread.SetData/GetData[ThreadStatic]等信息时,我发现这个想法很有意思。

此外,基于您使用CallContext.LogicalSetData而不是CallContext.SetData,我假设您希望利用与逻辑线程关联的信息将传播到子线程而不是只是想要一个“线程安全”的地方来存储信息。因此,如果您在应用程序的启动中设置(pr Push)AmbientActivity,然后不再推送任何活动,则任何后续线程也将成为同一活动的一部分,因为通过LogicalSetData存储的数据将由子线程继承。

如果你在第一次提出这个问题的同时学到了什么,我会非常有兴趣听到它。即使你没有,我也会有兴趣了解你在上下文中做了些什么。

目前,我正在为日志记录/跟踪维护一些上下文信息(类似于Trace.CorrelationManager.ActivityId和Trace.CorrelationManager.LogicalOpertionStack和log4net / NLog上下文支持)。我想保存一些上下文(当前应用程序,当前应用程序实例,当前活动(可能是嵌套的))以便在应用程序或WCF服务中使用,并且我希望“自动”跨WCF服务边界传播它。这是为了允许记录在中央存储库中的日志记录语句通过客户端/活动/等进行关联。我们将能够通过特定应用程序的特定实例查询和关联所有日志记录语句。可以在客户端或一个或多个WCF服务中生成日志记录语句。

ActivityId的WCF传播对我们来说不一定足够,因为我们想要传播(或者我们认为我们做的)不仅仅是ActivityId。此外,我们希望将此信息从Silverlight客户端传播到WCF服务,而Trace.CorrelationManager在Silverlight中不可用(至少在4.0版本中,可能会在将来提供)。

目前,我正在使用IClientMessageInspector和IDispatchMessageInspector对我们的“上下文”信息的传播进行原型设计。它看起来可能对我们有效。

关于对System.Web的依赖,NHibernate实现确实有一个“ReflectiveHttpContext”,它使用反射来访问HttpContext,因此不会有对System.Web的项目依赖。显然,如果将HttpContext配置为使用,则必须在部署应用程序的地方提供System.Web。

答案 1 :(得分:0)

我不知道如果希望只是提供对您的属性的线程安全访问,那么使用CallContext是正确的方法。如果是这种情况,则只需要锁定语句。

但是,您必须确保正确地应用

使用CallContext,您将获得线程安全访问,因为当调用进入不同的线程(或不同的存储,而不是)时,您将有单独的CallContext实例。但是,这与访问资源线程安全非常不同。

如果要跨多个线程共享相同的值,则可以使用lock语句。否则,如果您需要基于每个线程/调用的特定值,请使用CallContext,或者在Thread类或ThreadStatic属性(或任意数量的基于线程的存储机制)上使用静态GetData / SetData方法。 / p>