В обычном/синхронном/однопоточном консольном приложении NDC.Push отлично работает для управления «текущим элементом» (возможно, на нескольких уровнях вложенности, но в этом примере только 1 уровень).
Например:
private static ILog s_logger = LogManager.GetLogger("Program");
static void Main(string[] args)
{
BasicConfigurator.Configure();
DoSomeWork("chunk 1");
DoSomeWork("chunk 2");
DoSomeWork("chunk 3");
}
static void DoSomeWork(string chunkName)
{
using (NDC.Push(chunkName))
{
s_logger.Info("Starting to do work");
Thread.Sleep(5000);
s_logger.Info("Finishing work");
}
}
Это приведет к выходу журнала ожиданий, показывающему запись NDC «chunk X» справа от «Program» (шаблон по умолчанию для базового конфигуратора).
232 [9] INFO Часть программы 1 - Приступаем к работе
5279 [9] ИНФО Часть программы 1 - отделочные работы
5279 [9] INFO Программный фрагмент 2 - Начало работы
10292 [9] ИНФО Часть программы 2 - отделочные работы
10292 [9] INFO Программный фрагмент 3 - Начало работы
15299 [9] ИНФО Часть программы 3 - Отделочные работы
Однако я не могу понять, как поддерживать это, используя «обычные» асинхронные методы.
Например, пытаясь сделать это:
private static ILog s_logger = LogManager.GetLogger("Program");
static void Main(string[] args)
{
BasicConfigurator.Configure();
var task1 = DoSomeWork("chunk 1");
var task2 = DoSomeWork("chunk 2");
var task3 = DoSomeWork("chunk 3");
Task.WaitAll(task1, task2, task3);
}
static async Task DoSomeWork(string chunkName)
{
using (log4net.LogicalThreadContext.Stacks["NDC"].Push(chunkName))
//using (log4net.ThreadContext.Stacks["NDC"].Push(chunkName))
{
s_logger.Info("Starting to do work");
await Task.Delay(5000);
s_logger.Info("Finishing work");
}
}
Показывает, что все они запускаются нормально, но когда задача завершается в другом потоке, стек теряется (я надеялся, что log4net.LogicalThreadContext будет «осведомленным» о TPL).
234 [10] INFO Часть программы 1 - Приступаем к работе
265 [10] INFO Часть программы 2 - Приступаем к работе
265 [10] INFO Часть программы 3 - Приступаем к работе
5280 [7] Программа INFO (нулевая) - отделочные работы
5280 [12] Программа INFO (нулевая) - отделочные работы
5280 [12] Программа INFO (нулевая) - отделочные работы
Помимо добавления нового TaskContext (или подобного) в log4net, есть ли способ отслеживания такого рода активности?
На самом деле цель состоит в том, чтобы сделать это с помощью синтаксического сахара async/await - либо форсировать какое-то сходство с потоком, либо делать такие вещи, как сохранение параллельного словаря вокруг ключевого слова по задаче, вероятно, являются работоспособными вариантами, но я пытаюсь держаться как можно ближе к синхронная версия кода, насколько это возможно. :)
CallContext
в .NET 4.5 RTW для работы сasync
. Таким образом, NDC log4net и другие решения, использующиеLogical*Data
, будут работать, как и ожидалось, с методамиasync
(только в .NET 4.5). - person Stephen Cleary   schedule 08.03.2013