寻求一种通用的基于上下文的存储

发布于 2024-07-16 15:23:59 字数 1218 浏览 4 评论 0原文

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

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

Update

By safe 我不是指同步。 有关该问题的背景信息此处

First off, I wish context based storage was consistent across the framework!

With that said, I'm looking for an elegant solution to make these properties safe across ASP.NET, WCF and any other multithreaded .NET code. The properties are located in some low-level tracing helpers (these are exposed via methods if you're wondering why they're internal).

I'd rather not have a dependency on unneeded assemblies (like System.Web, etc). I don't want to require anyone using this code to configure anything. I just want it to work ;) That may be too tall of an order though...

Anyone have any tricks up their sleeves? (I've seen Spring's implementation)

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

Update

By safe I do not mean synchronized. Background on the issue here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

今天小雨转甜 2024-07-23 15:23:59

以下是 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/LogicalGetData、Thread.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。

Here is a link to (at least part of) NHibernate's "context" implementation:

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

It is not clear to me exactly where or how this comes into play in the context of NHibernate. That is, if I wanted to store some values in "the context" would I get "the context" from NHibernate and add my values? I don't use NHibernate, so I don't really know.

I suppose that you could look and determine for yourself if this kind of implementation would be useful to you. Apparently the idea would be to inject the desired implementation, depending on the type of application (ASP.NET, WCF, etc). That probably implies some configuration (maybe minimal if one were to use MEF to load "the" ICurrentSessionContext interface).

At any rate, I found this idea interesting when I found it some time ago while searching for information on CallContext.SetData/GetData/LogicalSetData/LogicalGetData, Thread.SetData/GetData, [ThreadStatic], etc.

Also, based on your use of CallContext.LogicalSetData rather than CallContext.SetData, I assume that you want to take advantage of the fact that information associated with the logical thread will be propagated to child threads as opposed to just wanting a "thread safe" place to store info. So, if you were to set (pr Push) the AmbientActivity in your app's startup and then not push any more activities, any subsequent threads would also be part of that same activity since data stored via LogicalSetData is inherited by child threads.

If you have learned anything in the meantime since you first asked this question I would be very interested in hearing about it. Even if you haven't, I would be interested in learning about what you are doing with the context.

At the moment, I am working on maintaining some context information for logging/tracing (similar to Trace.CorrelationManager.ActivityId and Trace.CorrelationManager.LogicalOpertionStack and log4net/NLog context support). I would like to save some context (current app, current app instance, current activity (maybe nested)) for use in an app or WCF service AND I want to propagate it "automatically" across WCF service boundaries. This is to allow logging statements logged in a central repository to be correlated by client/activity/etc. We would be able to query and correlate for all logging statements by a specific instance of a specific application. The logging statements could have been generated on the client or in one or more WCF services.

The WCF propagation of ActivityId is not necessarily sufficient for us because we want to propagate (or we think we do) more than just the ActivityId. Also, we want to propagate this information from Silverlight clients to WCF services and Trace.CorrelationManager is not available in Silverlight (at least not in 4.0, maybe something like it will be available in the future).

Currently I am prototyping the propagation of our "context" information using IClientMessageInspector and IDispatchMessageInspector. It looks like it will probably work ok for us.

Regarding a dependency on System.Web, the NHibernate implementation does have a "ReflectiveHttpContext" that uses reflection to access the HttpContext so there would not be a project dependency on System.Web. Obviously, System.Web would have to be available where the app is deployed if HttpContext is configured to be used.

深居我梦 2024-07-23 15:23:59

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

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

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

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

I don't know that using CallContext is the right move here if the desire is simply to provide thread-safe access to your properties. If that is the case, the lock statement is all you need.

However, you have to make sure you are applying it correctly.

With CallContext, you are going to get thread-safe access because you are going to have separate instances of CallContext when calls come in on different threads (or different stores, rather). However, that's very different from making access to a resource thread-safe.

If you want to share the same value across multiple threads, then the lock statement is the way to go. Otherwise, if you want specific values on a per-thread/call basis, use the CallContext, or use the static GetData/SetData methods on the Thread class, or the ThreadStatic attribute (or any number of thread-based storage mechanisms).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文