Why are ThreadStatic data unexpectedly distributed between threads?

I have a registration framework that I wrote that has the ability to track the "logging context". It has a built-in strategy, but most often I use the ThreadStatic option, which tracks the context in the [ThreadStatic] variable. I am trying to solve a problem with the logging context in a multi-threaded workflow. The goal is to have all the log entries for all calls in all methods and classes that share a common thread log in the same contextual information. Since each thread should theoretically receive its own ThreadStatic variable, the idea seemed easy.

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

In fact, it seems that ThreadStatic data is actually DETECTED by thread. This is contrary to everything I understand about ceiling processing. It was difficult for me to find out what the problem was until I added an additional log entry that was tracked when each thread cleared the thread context (all threads are executed in the main loop ... at the beginning, if the necessary messages are received, the context is initialized, and in the end of the finally clause is to reset it.) The following is the CONSISTENT logging:

[2011-12-15 16: 27: 21,233] [DEBUG] [TPI.LTI.Eventing.GroupCreatedNotificationHandler: TPI.LTI.Provisioning.Handlers.GroupCreatedNotificationHandler.WORKDEVELOPMENT.1_Thread: 324]: (ContextId = 184e82dd-152-b2b-152b-b2b-152b-b2bb-b2b a2c6-3e05b2365c04; TransactionID = 1a11130e-e8dd-4fa1-9107-3b46dcb4ffd6; HandlerName = GroupCreatedNotificationHandler; HandlerId = WORKDEVELOPMENT.1) Clicking an event for the tool '0967e031-398f-437df49fd4949fd4949fd4949fd4949fd4949fd494fd4949fd4949fd4949f2fd4949fdf47fd4949fdf49fdf49 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-4bb-- a2c6-3e05b2365c04; TransactionID = 1a11130e-e8dd-4fa1-9107-3b46dcb4ffd6; HandlerName = GroupCreatedNotificationHandler; HandlerId = WORKDEVELOPMENT.1) Getting an instance of the LTI tool for the tool example guid 0967e031-39844df-437fd-438fd-43df-438fd-43fd

[2011-12-15 16: 27: 21,318] [DEBUG] [TPI.LTI.Facades.LTIFacade: TPI.LTI.Provisioning.Handlers.GroupCreatedNotificationHandler.WORKDEVELOPMENT.1_Thread: 299]: (ContextId = 184e82dd-152b-4bb-- a2c6-3e05b2365c04; TransactionID = 1a11130e-e8dd-4fa1-9107-3b46dcb4ffd6; HandlerName = GroupCreatedNotificationHandler; HandlerId = WORKDEVELOPMENT.1) An LTI tool instance was found for the tool instance guid 0967e031-39844fdf-43df-431.

[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) Publish the event to TPI at 'HTTP://tpidev.petecmglt '...

[2011-12-15 16: 27: 21,428] [DEBUG] [TPI.LTI.Eventing.GroupCreatedNotificationHandler: TPI.LTI.Provisioning.Handlers.GroupCreatedNotificationHandler.WORKDEVELOPMENT.2_Thread: 301]: [LOG] Reset logging Context !!

[2011-12-15 16: 27: 21,442] [DEBUG] [TPI.LTI.Eventing.GroupCreatedNotificationHandler: TPI.LTI.Provisioning.Handlers.GroupCreatedNotificationHandler.WORKDEVELOPMENT.2_Thread: 299]: there is no pending message in the queue. The GroupCreatedNotificationHandler.WORKDEVELOPMENT.2 handler is waiting ...

[2011-12-15 16: 27: 22,282] [DEBUG] [TPI.LTI.Facades.TPIFacade: TPI.LTI.Provisioning.Handlers.GroupCreatedNotificationHandler.WORKDEVELOPMENT.1_Thread: 301]: The event was published in TPI.

[2011-12-15 16: 27: 22,283] [DEBUG] [TPI.LTI.Eventing.GroupCreatedNotificationHandler: TPI.LTI.Provisioning.Handlers.GroupCreatedNotificationHandler.WORKDEVELOPMENT.1_Thread: 301]: A response was received from the supplier:

You can see that in this particular case there are two threads: 1_Thread and 2_Thread. I italicized contextual data that should be included at the beginning of EVERY log entry for 1_Thread. I highlighted a point in 2_Thread where the logging context is reset. After this point, all 1_Thread context information is missing. In dozens of tests, contextual information for all threads is still lost after the context of logging reset on another.

I do not understand ThreadStatic? I have been writing C # code since 2001, and I have never experienced this before. There seems to be a new ThreadLocal<T> class in .NET 4, but I'm not sure if it just used ThreadStatic internally, and it would have the same problem, or if it functioned differently (and hopefully more reliably ) Any insight into this problem would be TRUE RECOGNIZED! Thanks!

+4
source share
2 answers

Because this field is not static . It applies only to static fields.

If it's 4.0, maybe see ThreadLocal<T>

+14
source

As @MarcGravell points out, your field is not static, which is the cause of your problem.

However, if the consumer was to save the return from GetLoggingContext , this value will be available for sharing between threads. Usually I try to use any ThreadStatic variables as details of the class implementation, and not expose them outside of it.

0
source

Source: https://habr.com/ru/post/1386615/


All Articles