5

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

话虽如此,我正在寻找一种优雅的解决方案,以使这些属性在 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;
        }
    }

更新

我所说的安全并不是同步的。关于这个问题的背景在这里

4

2 回答 2

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 必须在应用程序部署的位置可用。

于 2010-12-14T20:44:45.220 回答
0

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

但是,您必须确保正确应用它。

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

如果您想在多个线程之间共享相同的值,那么 lock 语句就是要走的路。否则,如果您想要基于每个线程/调用的特定值,请使用 CallContext,或使用 Thread 类的静态 GetData/SetData 方法,或 ThreadStatic 属性(或任何数量的基于线程的存储机制)。

于 2009-04-09T20:27:07.430 回答