5

「ロギングコンテキスト」を追跡する機能を備えた、自分で作成したロギングフレームワークがあります。[ThreadStatic]プラグ可能な戦略フレームワークがありますが、私が最も頻繁に使用するのは、変数のコンテキストを追跡するThreadStaticバリアントです。マルチスレッドワークフローでのログコンテキストの問題を解決しようとしています。目標は、共通のスレッドを共有するすべてのメソッドとクラスにわたるすべての呼び出しのすべてのログエントリに、同じコンテキスト情報を記録させることです。各スレッドは理論的には独自のThreadStatic変数を取得する必要があるため、アイデアは簡単に思えました。

public class ThreadStaticLoggingContextStrategy: ILoggingContextStrategy
{
    public ThreadStaticLoggingContextStrategy()
    {
        Debug.WriteLine("[INITIALIZE] A new instance of 'ThreadStaticLoggingContextStrategy' has been created.");
    }

    [ThreadStatic] private LoggingContext _context;

    public LoggingContext GetLoggingContext()
    {
        if (_context == null)
            _context = new LoggingContext();

        return _context;
    }
}

実際には、ThreadStaticデータは実際にはスレッド間で共有されているようです。これは、スレッドについて私が理解しているすべてに反します。各スレッドがスレッドコンテキストをクリアしたときに追跡する追加のログエントリをスローするまで、問題が何であるかを理解するのに苦労していました(すべてのスレッドはメインループで実行されます...最初に、必要なメッセージがあれば受信すると、コンテキストが初期化され、finally句の最後でリセットされます。)次のログはCONSISTENTです。

[2011-12-15 16:27:21,233] [DEBUG] [TPI.LTI.Eventing.GroupCreatedNotificationHandler:TPI.LTI.Provisioning.Handlers.GroupCreatedNotificationHandler.WORKDEVELOPMENT.1_Thread:324]:(ContextId = 184e82dd-152b-4bb5- a2c6-3e05b2365c04; TransactionId = 1a11130e-e8dd-4fa1-9107-3b46dcb4ffd6; HandlerName = GroupCreatedNotificationHandler; HandlerId = WORKDEVELOPMENT.1)ツール「0967e031-398f-437d-8949-2a17fe844df0」のイベントを http://tpidev.pにプッシュします。 com / tpi / lti / service /event ..。

[2011-12-15 16:27:21,259] [DEBUG] [TPI.LTI.Facades.LTIFacade:TPI.LTI.Provisioning.Handlers.GroupCreatedNotificationHandler.WORKDEVELOPMENT.1_Thread:299]:(ContextId = 184e82dd-152b-4bb5- a2c6-3e05b2365c04; TransactionId = 1a11130e-e8dd-4fa1-9107-3b46dcb4ffd6; HandlerName = GroupCreatedNotificationHandler; HandlerId = WORKDEVELOPMENT.1)ツールインスタンスguid 0967e031-398f-437d-8949-2a17fe844df0のLTIツールインスタンスの取得:

[2011-12-15 16:27:21,318] [DEBUG] [TPI.LTI.Facades.LTIFacade:TPI.LTI.Provisioning.Handlers.GroupCreatedNotificationHandler.WORKDEVELOPMENT.1_Thread:299]:(ContextId = 184e82dd-152b-4bb5- a2c6-3e05b2365c04; TransactionId = 1a11130e-e8dd-4fa1-9107-3b46dcb4ffd6; HandlerName = GroupCreatedNotificationHandler; HandlerId = WORKDEVELOPMENT.1)ツールインスタンスguid0967e031-398f-437d-8949-2a17fe844df0のLTIツールインスタンスが見つかりました。

[2011-12-15 16:27:21,352] [DEBUG] [TPI.LTI.Facades.TPIFacade:TPI.LTI.Provisioning.Handlers.GroupCreatedNotificationHandler.WORKDEVELOPMENT.1_Thread:299]:(ContextId = 184e82dd-152b-4bb5- a2c6-3e05b2365c04; TransactionId = 1a11130e-e8dd-4fa1-9107-3b46dcb4ffd6; HandlerName = GroupCreatedNotificationHandler; HandlerId = WORKDEVELOPMENT.1)「http://tpidev.pearsoncmg.com/tpi/lti/service/event」でのTPIへのイベントの公開..。。

[2011-12-15 16:27:21,428] [DEBUG] [TPI.LTI.Eventing.GroupCreatedNotificationHandler:TPI.LTI.Provisioning.Handlers.GroupCreatedNotificationHandler.WORKDEVELOPMENT.2_Thread:301]: [LOG]ロギングコンテキストをリセットしています!!

[2011-12-15 16:27:21,442] [DEBUG] [TPI.LTI.Eventing.GroupCreatedNotificationHandler:TPI.LTI.Provisioning.Handlers.GroupCreatedNotificationHandler.WORKDEVELOPMENT.2_Thread:299]:キューで保留中のメッセージはありません。GroupCreatedNotificationHandler.WORKDEVELOPMENT.2ハンドラーが待機しています...

[2011-12-15 16:27:22,282] [DEBUG] [TPI.LTI.Facades.TPIFacade:TPI.LTI.Provisioning.Handlers.GroupCreatedNotificationHandler.WORKDEVELOPMENT.1_Thread:301]:イベントがTPIに公開されました。

[2011-12-15 16:27:22,283] [DEBUG] [TPI.LTI.Eventing.GroupCreatedNotificationHandler:TPI.LTI.Provisioning.Handlers.GroupCreatedNotificationHandler.WORKDEVELOPMENT.1_Thread:301]:プロバイダーからの応答を受信しました:

この特定のケースでは、1_Threadと2_Threadの2つのスレッドがあることがわかります。1_Threadのすべてのログエントリの先頭に含まれることになっているコンテキストデータをイタリック体で示しています。ロギングコンテキストがリセットされる2_Threadのポイントを太字にしました。その後、1_Threadのコンテキスト情報はすべて失われます。これまでの数十のテストでは、ロギングコンテキストが別のスレッドでリセットされた後、すべてのスレッドのコンテキスト情報が失われます。

ThreadStaticを誤解していますか?私は2001年からC#コードを書いていますが、これまでこの動作を経験したことはありません。.NET 4には新しいThreadLocal<T>クラスがあるようですが、それがとにかく内部でThreadStaticを使用しただけで、同じ問題が発生するのか、それとも機能が異なる(そしてできればより確実に)のかはわかりません。この問題に関する洞察大変感謝しております!ありがとう!

4

2 に答える 2

15

そのフィールドは静的ではないためです。静的フィールドにのみ適用されます。

これが4.0の場合、多分見てくださいThreadLocal<T>

于 2011-12-15T23:45:57.140 に答える
0

@MarcGravellが指摘しているように、フィールドは静的ではなく、これが問題の原因です。

ただし、コンシューマーがGetLoggingContextこの値からのリターンを格納する場合は、スレッド間で共有できます。私は通常、ThreadStatic変数をクラスの外部に公開するのではなく、クラスの実装の詳細として使用しようとします。

于 2011-12-15T23:50:46.943 に答える