In un'app console sincrona/sincrona/a thread singolo, NDC.Push funziona correttamente per la gestione dell'elemento corrente (potenzialmente a più livelli di nidificazione, ma solo 1 livello per questo esempio).come gestire uno stack log4net simile a NDC con metodi async/await? (per-Task stack?)
Ad esempio:
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");
}
}
Ciò comporterà l'uscita si aspettano log, mostrando un 'pezzo X' ingresso NDC appena a destra del 'Programma' (il modello predefinito per il configuratore di base)
232 [9] INFO Programma pezzo 1 - Iniziare a fare il lavoro
5279 [9] INFO Programma pezzo 1 - Finiture edili
5279 [9] INFO programma pezzo 2 - Avvio di fare un lavoro
10292 [9] Programma INFO pezzo 2 - Finiture edili
10292 [9] INFO Programma pezzo 3 - Iniziare a fare il lavoro
15299 [9] INFO Programma pezzo 3 - Finiture edili
Comunque, io non riesco a capire come mantenere che l'utilizzo di metodi asincroni 'normali'.
Per esempio, cercando di fare questo:
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");
}
}
mostra loro tutti a partire "normalmente", ma quando l'attività viene completata su un thread diverso, lo stack è perduto (speravo la log4net.LogicalThreadContext avrei essere TPL-'ware 'credo).
234 [10] INFO Programma pezzo 1 - Iniziare a fare il lavoro
265 [10] INFO programma pezzo 2 - Avvio di fare un lavoro
265 [10] INFO Programma pezzo 3 - Avvio per fare il lavoro
5280 [7] INFO programma (null) - Finiture
5280 [12] INFO programma (null) - Finiture edili
5280 [12] INFO programma (null) - Finiture edili
Al di fuori di aggiunta di un nuovo TaskContext (o simile) per log4net, c'è un modo di tracciare questo tipo di attività?
L'obiettivo è davvero farlo con lo zucchero syntax asincrono/attendi: forzare un certo tipo di affinità per i thread o fare cose come mantenere un dizionario concorrente attorno a un compito per tipo sono probabilmente opzioni praticabili, ma sto cercando di mantenere il più vicino possibile alla versione sincrona del codice. :)
FYI, ho scoperto di recente che Microsoft ha risolto 'CallContext' in .NET 4.5 RTW per lavorare con' async'. Pertanto, NDC di log4net e altre soluzioni che utilizzano 'Logical * Data' funzioneranno come previsto con i metodi' async' (solo su .NET 4.5). –
@StephenCleary fantastico! Grazie! –
Non sono sicuro che si tratti di un problema proveniente dal contesto del thread logico. L'implementazione di log4net mi sembra sbagliata perché i thread padre e figlio condividono lo stesso stack. Il bambino dovrebbe ricevere un clone dello stack genitore in modo che se il genitore modifica lo stack non perturba il bambino ... –