2

同じ操作に別のスレッドを使用するときに、WCF に Trace.CorrelationManager のプロパティを伝達させるにはどうすればよいですか?

WCF がスレッド アフィニティを保証しないことはわかっています。したがって、基本的に 1 つのスレッドが要求を開始し、別のスレッドがそれを終了することができます。この動作を再現すると、最初のスレッドに Trace.Correlation.ActivityId と Trace.Correlation.LogicalOperationStack の 2 つのプロパティが正しく設定されていることがわかります。WCF は別のスレッドで操作を終了しましたが、プロパティは伝達されませんでした。

これを回避するには、CorrelationManager の使用を放棄する必要があり、おそらく新しいスレッドに伝達されることがわかっている OperationContext に ActivityId を格納する必要があります (ここで間違っている場合は修正してください)。もちろん、より多くの作業が必要であり、その単一のプロパティを使用するほどエレガントではないため、これを行いたくありません。

これを回避する方法について他のアイデアはありますか? どういうわけかこれを伝播するように WCF に指示できますか?

ありがとう、モハメッド

4

1 に答える 1

1

これを回避するために、Trace.CorrelationManager プロパティの使用をやめました。これらのプロパティの代わりに、Extension クラスに追加したカスタム プロパティを使用します。これで、この拡張機能の ActivityId と LogicalOperationStack を直接変更できるようになりました。これは、Trace.CorrelationManager プロパティを使用するのと同じくらい便利な操作要求の存続期間中にアクセスできます。

プラスとして、リクエストの存続期間中に使用したい他のカスタム プロパティを保存できます。この好例は、サポート性を向上させるためにロギングにも使用できる顧客 ID またはリソース ID です。

using System;
using System.Collections;
using System.ServiceModel;

namespace MyNamespace
{
    /// <summary>
    /// Class that represents an extension used to store custom data for the life of a WCF OperationContext.
    /// </summary>
    public class OperationContextExtension : IExtension<OperationContext>
    {
        /// <summary>The activity id of the operation.</summary>
        private Guid activityId;

        /// <summary>The logical operation stack of the operation.</summary>
        private Stack logicalOperationStack;

        /// <summary>
        /// Initializes a new instance of the OperationContextExtension class.
        /// </summary>
        public OperationContextExtension()
        {
            this.logicalOperationStack = new Stack();
        }

        /// <summary>
        /// Gets the current OperationContextExtension extension from the OperationContext.
        /// </summary>
        public static OperationContextExtension Current
        {
            get
            {
                OperationContextExtension context;
                if (OperationContext.Current == null)
                {
                    context = null;
                }
                else
                {
                    context = OperationContext.Current.Extensions.Find<OperationContextExtension>();
                }

                return context;
            }
        }

        /// <summary>
        /// Gets or sets the activity id for the current operation.
        /// </summary>
        public Guid ActivityId
        {
            get { return this.activityId; }
            set { this.activityId = value; }
        }

        /// <summary>
        /// Gets the LogicalOperationStack for the current operation.
        /// </summary>
        public Stack LogicalOperationStack
        {
            get { return this.logicalOperationStack; }
        }

        /// <summary>
        /// Enables an extension object to find out when it has been aggregated. Called when the extension is added 
        /// to the System.ServiceModel.IExtensibleObject Extensions property.
        /// </summary>
        /// <param name="owner">The extensible object that aggregates this extension.</param>
        public void Attach(OperationContext owner)
        {
            // Use this method for request initialization if needed
        }

        /// <summary>
        /// Enables an object to find out when it is no longer aggregated. Called when an extension is removed 
        /// from the System.ServiceModel.IExtensibleObject Extensions property.
        /// </summary>
        /// <param name="owner">The extensible object that aggregates this extension.</param>
        public void Detach(OperationContext owner)
        {
            // Use this method for request cleanup if needed
        }
    }
}

この拡張機能を OperationContext に追加する必要があります。まず、WCF 動作拡張への適切なフックを見つける必要があります。一般的なオプションは、IEndpointBehavior に適用される MessageInspector を使用することです。これを達成する方法についての素晴らしい読み物を次に示します (私の例が役に立たない場合は、クイック検索で多くの有用な例が得られます)。

フックを作成したら、次の行を使用して、できるだけ早く拡張機能を OperationContext に追加します。

// Add an extension object to the current operation context to track custom state across all threads
// for the life of the operation
OperationContext.Current.Extensions.Add(new OperationContextExtension());

これで、コード ワークフローの実質的にどこからでも、ActivityId プロパティと LogicalOperationStack、またはこのクラスで定義したその他のプロパティにアクセスできます。

LogOperation(OperationContextExtension.Current.ActivityId, logMessage);
OperationContextExtension.Current.LogicalOperationStack.Push("Starting 'Nested Activity' 3...");

お役に立てれば!

-モハメッド

于 2012-05-13T04:31:43.470 に答える