8

最近、Dynamics CRM 2011 で 1 つのプラグインの実行 (つまり、Execute()メソッドのパス) が同じスレッドにとどまることが保証されているかどうかという質問がいくつか出てきました。

Ambient Context パターンを使用してトレースを実装し、トレースが必要なクラスにトレース サービスを渡さないようにしたいと考えています。問題は、私たちが知っているように、プラグインは登録されたステップごとに 1 回だけインスタンス化され、同じインスタンスから後続のすべての操作を提供することです。つまり、現在のインスタンスTracing.Currentを割り当てるような静的プロパティを持つことはできず、問題ありません。ITracingService私がそれを行った場合、最後に開始された操作は、まだ実行されている可能性のある他のすべての操作のインスタンスを上書きします (この種の同時実行は珍しくありません)。

メソッドの下のすべてが同じスレッドに残っていることを確認できれば、静的フィールドExecute()の属性を利用してアンビエント コンテキストを使用できます。[ThreadStatic]

public static class Tracing
{
    [ThreadStatic]
    private static ITracingService _current;

    public static ITracingService Current
    {
        get
        {
            if (null == _current)
            {
                _current = new NullTracingService();
            }

            return _current;
        }

        set { _current = value; }
    }
}

メソッドに入るとこれを設定Execute()し、最後にクリアして、トレース サービス インスタンスへの参照が削除されるようにします。

MSCRMプラグインのコンテキストでのスレッド化について私が知ることができる唯一のことは、明らかに個々のスレッドがThreadPoolから来ているということです.

MSCRM プラグインでスレッド化がどのように処理されるか、またはこの特別なケースで SOLID コードを使用してトレースの分野横断的な懸念をどのようにエレガントに処理できるかについての他のアイデアを持っている人はいますか (AOP/動的傍受はここではオプションではありません)?

ヘルプとポインタをありがとう。

4

3 に答える 3

3

シンプルで賢明な答えは、それをするときに痛い場合は、それをしないことです. :)

アンビエント コンテキスト パターンを使用するというあなた自身の要件は、CRM のデザイン パターンと矛盾しています。CRM がどのように機能するかを考えてみてくださいIServiceProvider。トレース サービスなど、必要なものがすべて含まれています。複雑なマルチスレッド化と最適化をすべて処理し、派手なパターンや静的変数、またはスレッド化のトリックで裏をかこうとしないように要求するだけです。

私の推奨事項は、同じパターンを使用IServiceProviderすることです。必要なクラスまたはメソッドに を渡します。はるかに単純です。さらに、後で奇妙なバグが発生した場合、Microsoft のエンジニアの裏をかくことができたかどうかについては疑問を抱くことはありません。:)

于 2012-12-15T20:00:07.470 に答える
1

CRM は単一のプラグイン オブジェクトを作成し、必要に応じてスレッドを使用して要求を処理します。したがって、1 つのプラグイン オブジェクトに対して複数のスレッドが同時に実行されることだけは確実です。

スレッドは IIS を通じて管理され、可能であれば再利用されます。したがって、毎回Execute呼び出されるようにしたい場合は、 newITracingServiceを設定する必要があります。毎回Execute呼び出されることを確認したいだけの場合は、それifを確認するステートメントを実行するだけです。

バッキング変数はであるため、スレッドの問題について心配する必要はありませんが、IIS はスレッドを再利用しようとするため、が呼び出されるThreadStaticたびに空になることはありません。Execute

于 2012-12-17T14:09:11.317 に答える
0

ここでプラグイン/スレッド/静的な問題全体を推測することしかできないのではないかと心配していますが、あなたが提案していることは少し複雑に思えます. 代わりに、Trace Listener の使用を検討しましたか?

アプリケーション全体で使用する場合Trace.Writeline、単一の Trace Listener がこれらすべてのメッセージをキャプチャします。そうすれば、トレース オブジェクトを渡す必要はありません。

例えば:

Execute(...)
{
    if(System.Diagnostics.Trace.Listeners
        .Count(l => typeof(l) == MyCustomTraceListener) == 0)
    {
        System.Diagnostics.Trace.Listeners.Add(new MyCustomTraceListener());
    }

    DoWork();
}

DoWork()
{   
    System.Diagnostics.Trace.WriteLine("I'm doing work!");
}

関連リンク:

トレース リスナーチュートリアル: カスタム トレース リスナーの作成

于 2012-12-16T11:31:39.450 に答える