2010-10-01 22 views
27

MISE À JOUR le 18/11/2014 - Lors de la navigation dans le référentiel source de log4net, j'ai trouvé que l'implémentation de LogicalThreadContext a été modifiée en novembre 2011 pour qu'elle stocke ses propriétés en utilisant CallContext.LogicalSetData (et les obtient en utilisant LogicalGetData). Ceci est important car cela signifie que LogicalThreadContext devrait maintenant fonctionner correctement. Toutes les données stockées dans LogicalThreadContext doivent être "transmises" à tous les threads ou tâches enfants. Cela se compare à ThreadContext (et à l'ancienne implémentation de LogicalThreadContext) où les données stockées dans le contexte resteront locales au thread actuel et ne seront PAS transmises aux threads/tâches enfants.Quelle est la différence entre log4net.ThreadContext et log4net.LogicalThreadContext?

Si vous êtes intéressé, voici le changement:

http://svn.apache.org/viewvc/logging/log4net/trunk/src/log4net/Util/LogicalThreadContextProperties.cs?r1=1165341&r2=1207948&diff_format=h

Espérons que quelqu'un qui se passe sur cette vieille question trouvera ces informations utiles. Log4net fournit deux objets différents de "contexte de thread": ThreadContext et LogicalThreadContext, chacun ayant un sac de propriétés, Properties. ThreadContext a un sac ThreadContextProperties tandis que LogicalThreadContext a un sac LogicalThreadContextProperties.

ThreadContext est peut-être plus communément appelé "MDC". LogicalContext est peut-être plus communément appelé "LDC". Je vais utiliser le nom court pour le reste de ce message.

MDC.Properties est implémenté en utilisant System.Threading.Thread.SetData tandis que LDC.Properties est implémenté en utilisant System.Runtime.Remoting.Messaging.CallContext.SetData. Pour comparer, NLog expose seulement "MDC" (maintenant connu comme MappedDiagnosticContext) pour stocker les propriétés locales de thread. L'implémentation de NLog utilise System.Threading.Thread.SetData, donc son implémentation est la même que celle de log4net.

Dans les deux log4net et NLog, les propriétés "MDC" sont stockées dans un dictionnaire qui est lui-même stocké dans le stockage local de threads.

Dans un cas comme celui-ci, le stockage du dictionnaire dans une variable de membre de classe décorée avec [ThreadStatic] aurait-il été équivalent? Quelle est la déclaration équivalente (ou similaire) utilisant la nouvelle classe ThreadLocal de .NET 4.0?

En fin de compte, quelle est la différence réelle, pratique, entre LDC et MDC? Même après avoir lu les sujets MSDN liés ci-dessus, ce n'est pas clair pour moi. Quand utiliseriez-vous vraiment l'un par rapport à l'autre? Il semble que la grande majorité des références/exemples que je vois pour log4net et le contexte est pour GDC (global - ce que je comprends), NDC (imbriqué - que je comprends aussi), et MDC. La plupart des références que je peux trouver à LDC (ou LogicalThreadContext) lorsque googling sont liés à checkins dans les référentiels de code source de log4net, pas l'utilisation réelle. Les PMA ne posent presque jamais de questions ou d'exemples.

J'ai trouvé le lien this qui offre de très bonnes informations sur la différence de l'un des développeurs de log4net, Nicko Cadell, mais ce n'est toujours pas clair pour moi.

Une plus grande question, pas directement liée à log4net est ce qui est la différence pratique entre Thread.SetData et CallContext.SetData?

Selon l'article MSDN CallContext, les données CallContext peuvent être propagées vers un autre AppDomain. Pour être propagé, un élément de données stocké dans CallContext doit exposer l'interface ILogicalThreadAffinative. Donc, cela semble être une différence entre Thread.SetData et CallContext.

Selon le lien Nicko Cadell, log4net n'implémente pas ILogicalThreadAffinative, donc les propriétés LDC ne seront pas propagées.

Peut-être qu'il y a assez ici que je devrais être capable de répondre à ma propre question, peut-être pas. Je travaille toujours à la compréhension.

Si vous utilisez log4net, utilisez-vous chaque MDC, LDC, les deux? Si vous utilisez MDC, est-ce parce que la plupart des exemples du «monde réel» semblent l'utiliser? Si vous utilisez LDC, avez-vous une raison spécifique de l'utiliser? Si vous utilisez les deux, comment choisissez-vous quand utiliser quoi?

Notez que j'ai vu certains articles concernant MDC (et peut-être LDC) peuvent ne pas fonctionner correctement dans les applications ASP.net en raison de la commutation de threads. Je ne suis pas particulièrement intéressé par ce problème car je ne travaille pas sur ASP.net.

En fait, j'ai trouvé quelques messages utiles ici sur SO qui pourraient contribuer à la discussion:

What are best practices for using thread local storage in .NET?

.Net: Logical thread and Thread Local Storage?

Merci à l'avance!

Répondre

8

Attention: il s'agit de devinettes. Supposons que vous écrivez un serveur et que le fait de répondre à une demande signifie que vous devez parler à plusieurs services différents. En tant que développeur très moderne, vous effectuez ces requêtes de manière asynchrone, en vous coordonnant lorsque tout est répondu (ou expiré) afin de répondre à la requête d'origine.

Cela signifie que le travail correspondant à une requête unique est dispersé parmi de nombreux threads différents (traitement des réponses de service Web de manière asynchrone). I suspect que CallContext est utilisé pour propager le "tout ce que je fais est à cause de cette demande entrante" à différents threads, de sorte que vous pouvez rassembler tous les journaux pour cette demande ensemble. ThreadContext ne serait pas utile là-bas. Notez que je suppose que tout le travail est en train d'être effectué dans un seul AppDomain, donc votre problème ne serait pas un problème.

+0

En fait, cela ne semble pas être le cas, mon expérience actuelle avec .net 4.5 web api et les demandes asynchrones est que le CallContext n'est pas transmis, il est plutôt limité à cette invocation du thread. J'ai répondu à un fil qui m'a conduit ici avec quelques détails http://stackoverflow.com/questions/4507968/whats-the-difference-between-log4net-threadlogicalcontext-and-log4net-threadcon –

+0

@TommyG .: Troisième tentative à ce commentaire :) Il semble qu'il y ait plusieurs facteurs en jeu ici, et ils dépendent à la fois de la version de l'infrastructure et de la version de log4net. Voir http://stackoverflow.com/questions/9781321/ - il semble que 'CallContext' * devrait * fonctionner, mais il y a (ou il y avait) un bogue dans log4net qui empêche' LogicalThreadContext' de bien jouer avec. –

+0

Salut Jon, c'était aussi ma compréhension du LogicalThreadContext à la lecture, mais merci de partager cette autre question, c'est une bonne information. –