.net - example - ¿Cuál es la diferencia entre log4net.ThreadContext y log4net.LogicalThreadContext?
nlog tutorials (1)
Advertencia: esto es conjetura.
Supongamos que está escribiendo un servidor, y atender una solicitud significa que tiene que hablar con varios servicios diferentes. Siendo un desarrollador totalmente moderno, realiza estas solicitudes de forma asincrónica, coordinando cuándo se respondió todo (o se agotó el tiempo de espera) para responder a la solicitud original.
Eso significa que el trabajo correspondiente a una sola solicitud se encuentra disperso entre muchos hilos diferentes (procesando las respuestas del servicio web de forma asincrónica). Sospecho que CallContext
se usa para propagar "todo lo que hago es debido a esta única solicitud entrante" a diferentes subprocesos, para que pueda reunir todos los registros de esa solicitud. ThreadContext
no ayudaría allí. Tenga en cuenta que supongo que todo el trabajo se está realizando en un solo dominio de aplicación, por lo que su preocupación no sería un problema.
ACTUALIZADO el 18/11/2014 - Mientras navegaba en el repositorio de fuentes de log4net, encontré que la implementación de LogicalThreadContext se modificó en noviembre de 2011 para que almacene sus propiedades usando CallContext.LogicalSetData (y las obtiene usando LogicalGetData). Esto es importante porque eso significa que LogicalThreadContext ahora debería funcionar correctamente. Todos los datos almacenados en LogicalThreadContext deben "fluir" a cualquier subproceso o tarea hijo. Esto se compara con ThreadContext (y la implementación anterior de LogicalThreadContext) donde los datos almacenados en el contexto permanecerían locales al hilo actual y NO fluirían a hilos secundarios / tareas.
Si estás interesado, aquí está el cambio:
Con suerte, a alguien que esté pasando por esta vieja pregunta le resultará útil esta información.
log4net proporciona dos objetos diferentes de "contexto de subprocesos": ThreadContext y LogicalThreadContext , cada uno de los cuales tiene una bolsa de propiedades, Propiedades. ThreadContext tiene una bolsa ThreadContextProperties mientras que LogicalThreadContext tiene una bolsa LogicalThreadContextProperties .
ThreadContext es quizás más comúnmente conocido como "MDC". LogicalContext es quizás más comúnmente conocido como "LDC". Usaré el nombre corto para el resto de esta publicación.
MDC.Properties se implementa mediante System.Threading.Thread.SetData mientras que LDC.Properties se implementa utilizando System.Runtime.Remoting.Messaging.CallContext.SetData .
Para comparación, NLog solo expone "MDC" (ahora conocido como MappedDiagnosticContext) para almacenar propiedades locales de subprocesos. La implementación de NLog usa System.Threading.Thread.SetData, por lo que su implementación es la misma que la de log4net.
Tanto en log4net como en NLog, las propiedades "MDC" se almacenan en un diccionario que se almacena en el almacenamiento local de subprocesos.
En un caso como este, ¿sería equivalente almacenar el diccionario en una variable de miembro de clase decorada con [ThreadStatic]?
[ThreadStatic]
private static IDictionary<string, string> threadProperties;
¿Cuál es la declaración equivalente (o similar) usando la nueva clase ThreadLocal de .NET 4.0?
En definitiva, ¿cuál es la diferencia real y práctica entre LDC y MDC? Incluso después de leer los temas de MSDN vinculados anteriormente, no está claro para mí. ¿Cuándo usarías realmente uno sobre el otro? Parece que la gran mayoría de las referencias / ejemplos que veo para log4net y el contexto es para GDC (global, que entiendo), NDC (anidado, que también entiendo) y MDC. La mayoría de las referencias que puedo encontrar en LDC (o LogicalThreadContext) al buscar en Google están relacionadas con los checkins en los repositorios de código fuente de log4net, no con el uso en el mundo real. LDC casi nunca aparece en preguntas o ejemplos.
Encontré this enlace que ofrece información bastante buena sobre la diferencia de uno de los desarrolladores de log4net, Nicko Cadell, pero aún no está claro para mí.
Una pregunta más amplia, que no está directamente relacionada con log4net, ¿cuál es la diferencia práctica entre Thread.SetData y CallContext.SetData?
De acuerdo con el artículo de CallContext MSDN, los datos de CallContext se pueden propagar a otro AppDomain. Para propagarse, un elemento de datos almacenado en el CallContext debe exponer la interfaz ILogicalThreadAffinative . Entonces, esa parece ser una diferencia entre Thread.SetData y CallContext.
Según el enlace de Nick Cadell, log4net no implementa ILogicalThreadAffinative, por lo que las propiedades de LDC no se propagarán.
Tal vez haya suficiente aquí que debería ser capaz de responder mi propia pregunta, tal vez no. Todavía estoy trabajando en entender.
Si usa log4net, ¿todos usan MDC, LDC, ambos? Si usa MDC, ¿es porque la mayoría de los ejemplos del "mundo real" parecen usarlo? Si usa LDC, ¿tiene una razón específica para usarlo? Si usa ambos, ¿cómo elige cuándo usarlos?
Tenga en cuenta que he visto algunos artículos sobre MDC (y tal vez LDC) que quizás no funcionen correctamente en las aplicaciones ASP.net debido al cambio de subprocesos. No estoy particularmente interesado en este problema ya que no estoy trabajando en ASP.net.
De hecho, he encontrado un par de publicaciones útiles aquí en SO que podrían contribuir a la discusión:
¿Cuáles son las mejores prácticas para usar el almacenamiento local de subprocesos en .NET?
.Net: hilo lógico y Thread Local Storage?
¡Gracias por adelantado!