В чем разница между log4net.ThreadContext и log4net.LogicalThreadContext? - PullRequest
28 голосов
/ 01 октября 2010

ОБНОВЛЕНО 18.11.2014 - Просматривая исходный репозиторий log4net, я обнаружил, что реализация LogicalThreadContext была изменена в ноябре 2011 года, так что он сохраняет свои свойства с помощью CallContext.LogicalSetData (и получает их с помощью LogicalGetData). Это важно, потому что это означает, что LogicalThreadContext теперь должен работать правильно. Любые данные, хранящиеся в LogicalThreadContext, должны передаваться любым дочерним потокам или задачам. Это сравнивается с ThreadContext (и старой реализацией LogicalThreadContext), где данные, хранящиеся в контексте, остаются локальными для текущего потока и НЕ передаются дочерним потокам / задачам.

Если вы заинтересованы, вот изменение:

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

Надеюсь, кто-то, кто встретит этот старый вопрос, найдет эту информацию полезной.

log4net предоставляет два различных объекта «контекста потока»: ThreadContext и LogicalThreadContext , каждый из которых имеет набор свойств Properties. ThreadContext имеет ThreadContextProperties мешок, в то время как LogicalThreadContext имеет LogicalThreadContextProperties мешок.

ThreadContext, возможно, более широко известен как "MDC". LogicalContext, возможно, более широко известен как «LDC». Я буду использовать короткое имя для остальной части этого поста.

MDC.Properties реализован с использованием System.Threading.Thread.SetData , а LDC.Properties - с использованием System.Runtime.Remoting.Messaging.CallContext.SetData .

Для сравнения, NLog предоставляет только «MDC» (теперь известный как MappedDiagnosticContext) для хранения локальных свойств потока. Реализация NLog использует System.Threading.Thread.SetData, поэтому его реализация такая же, как в log4net.

Как в log4net, так и в NLog свойства "MDC" хранятся в словаре, который сам хранится в локальном хранилище потока.

В таком случае сохранение словаря в переменной члена класса, украшенной [ThreadStatic], было бы эквивалентно?

[ThreadStatic]
private static IDictionary<string, string> threadProperties;

Каким может быть эквивалентное (или подобное) объявление с использованием нового класса ThreadLocal в .NET 4.0?

В конечном счете, какова реальная, практическая разница между НРС и МДС? Даже после прочтения вышеупомянутых тем MSDN мне это не понятно. Когда бы вы действительно использовали один поверх другого? Кажется, что подавляющее большинство ссылок / примеров, которые я вижу для log4net и context, относится к GDC (глобальный - который я понимаю), NDC (вложенный - который я также понимаю) и MDC. Большинство ссылок, которые я могу найти на LDC (или LogicalThreadContext) при поиске в Google, относятся к регистрации в репозиториях исходного кода log4net, а не к реальному использованию. НРС почти никогда не подходит к вопросам или примерам.

Я нашел эту ссылку, которая предлагает довольно хорошую информацию о разнице с одним из разработчиков log4net, Нико Каделлом, но она мне до сих пор не ясна.

Более крупный вопрос, не связанный напрямую с log4net, в чем заключается практическая разница между Thread.SetData и CallContext.SetData?

Согласно статье CallContext MSDN, данные CallContext могут распространяться на другой домен приложения. Для распространения элемент данных, хранящийся в CallContext, должен предоставлять интерфейс ILogicalThreadAffinative . Так что, похоже, это одно из различий между Thread.SetData и CallContext.

Согласно ссылке Nicko Cadell, log4net не реализует ILogicalThreadAffinative, поэтому свойства LDC распространяться не будут.

Может, здесь достаточно, чтобы я мог ответить на свой вопрос, а может и нет. Я все еще работаю над пониманием.

Если вы используете log4net, вы все используете MDC, LDC, оба? Если вы используете MDC, это потому, что большинство примеров из "реального мира", кажется, используют его? Если вы используете LDC, у вас есть конкретная причина для его использования? Если вы используете оба, как вы выбираете, когда использовать какой?

Обратите внимание, что я видел некоторые статьи, касающиеся MDC (и, возможно, LDC), которые могут работать неправильно в приложениях ASP.net из-за переключения потоков. Меня эта проблема не особо интересует, так как я не работаю в ASP.net.

На самом деле, я нашел пару полезных постов здесь на SO, которые могли бы способствовать обсуждению:

Каковы рекомендации по использованию локального хранилища потоков в .NET?

.Net: логический поток и локальное хранилище потока?

Заранее спасибо!

1 Ответ

8 голосов
/ 01 октября 2010

Предупреждение: это догадки.

Предположим, вы пишете сервер, и обработка запроса означает, что вам нужно общаться с несколькими различными службами. Будучи совершенно современным разработчиком, вы делаете эти запросы асинхронно, координируя, когда все ответили (или истекло время ожидания), чтобы ответить на исходный запрос.

Это означает, что работа, соответствующая одному запросу, разбросана по многим различным потокам (асинхронная обработка ответов веб-службы). Я подозреваю , что CallContext используется для распространения "всего, что я делаю, из-за этого одного входящего запроса" в разные потоки, чтобы вы могли собрать все журналы для этого запроса вместе. ThreadContext не поможет там. Обратите внимание, что я предполагаю, что вся работа выполняется в одном домене приложений, поэтому у вас не возникнет проблем.

...