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/LogicalGetDataいずれにせよ、このアイデアは、この前、Thread.SetData/GetData[ThreadStatic]、 などの情報を検索しているときに見つけたときに興味深いものでした。

CallContext.LogicalSetDataまた、ではなくの使用に基づいてCallContext.SetData、「スレッドセーフ」な場所に情報を保存するだけでなく、論理スレッドに関連付けられた情報が子スレッドに伝達されるという事実を利用したいと思います。したがって、アプリの起動時に AmbientActivity を設定 (pr Push) し、それ以上アクティビティをプッシュしない場合、LogicalSetData を介して格納されたデータは子スレッドによって継承されるため、後続のスレッドも同じアクティビティの一部になります。

あなたが最初にこの質問をしてから、それまでに何か学んだことがあれば、ぜひ聞いてみたいと思います. たとえそうでないとしても、あなたがコンテキストで何をしているのかを知りたいと思います。

現在、ロギング/トレース用のコンテキスト情報の維持に取り組んでいます (Trace.CorrelationManager.ActivityId と Trace.CorrelationManager.LogicalOpertionStack と log4net/NLog コンテキスト サポートに似ています)。アプリまたは WCF サービスで使用するために、いくつかのコンテキスト (現在のアプリ、現在のアプリ インスタンス、現在のアクティビティ (ネストされている可能性があります)) を保存し、それを WCF サービスの境界を越えて "自動的に" 伝達したいと考えています。これは、中央リポジトリに記録されたロギング ステートメントを client/activity/etc で関連付けることができるようにするためです。特定のアプリケーションの特定のインスタンスによって、すべてのログ ステートメントを照会して関連付けることができます。ログ ステートメントは、クライアントまたは 1 つ以上の WCF サービスで生成されている可能性があります。

ActivityId の WCF 伝達は必ずしも十分ではありません。なぜなら、ActivityId 以外のものを伝達したい (または伝達したいと考えている) からです。また、この情報を Silverlight クライアントから WCF サービスに伝達したいのですが、Trace.CorrelationManager は Silverlight では使用できません (少なくとも 4.0 では使用できません。将来的には同様のものが使用可能になる可能性があります)。

現在、IClientMessageInspector と IDispatchMessageInspector を使用して、「コンテキスト」情報の伝播のプロトタイプを作成しています。私たちにとってはおそらくうまくいくようです。

System.Web への依存関係については、NHibernate の実装にはリフレクションを使用して HttpContext にアクセスする「ReflectiveHttpContext」があるため、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 に答える