Я реализую свою собственную структуру ведения журнала. Ниже приведен мой BaseLogger
, который получает записи журнала и отправляет их в фактический Logger, который реализует метод abstract Log
.
Я использую C# TPL для асинхронного ведения журнала. Я использую потоки вместо TPL. (Задача TPL не содержит реального потока. Поэтому, если все потоки приложения завершатся, задачи также остановятся, что приведет к потере всех «ожидающих» записей журнала.)
public abstract class BaseLogger
{
// ... Omitted properties constructor .etc. ... //
public virtual void AddLogEntry(LogEntry entry)
{
if (!AsyncSupported)
{
// the underlying logger doesn't support Async.
// Simply call the log method and return.
Log(entry);
return;
}
// Logger supports Async.
LogAsync(entry);
}
private void LogAsync(LogEntry entry)
{
lock (LogQueueSyncRoot) // Make sure we ave a lock before accessing the queue.
{
LogQueue.Enqueue(entry);
}
if (LogThread == null || LogThread.ThreadState == ThreadState.Stopped)
{ // either the thread is completed, or this is the first time we're logging to this logger.
LogTask = new new Thread(new ThreadStart(() =>
{
while (true)
{
LogEntry logEntry;
lock (LogQueueSyncRoot)
{
if (LogQueue.Count > 0)
{
logEntry = LogQueue.Dequeue();
}
else
{
break;
// is it possible for a message to be added,
// right after the break and I leanve the lock {} but
// before I exit the loop and task gets 'completed' ??
}
}
Log(logEntry);
}
}));
LogThread.Start();
}
}
// Actual logger implimentations will impliment this method.
protected abstract void Log(LogEntry entry);
}
Обратите внимание, что AddLogEntry
можно вызывать из нескольких потоков одновременно.
Мой вопрос: возможно ли, чтобы эта реализация теряла записи журнала? Меня беспокоит, можно ли добавить запись журнала в очередь, сразу после того, как мой поток существует в цикле с оператором break и выходит из блока блокировки, который находится в предложении else, а поток все еще находится в Состояние «Работает».
Я понимаю, что, поскольку я использую очередь, даже если я пропущу запись, следующий запрос в журнал также подтолкнет пропущенную запись. Но это неприемлемо, особенно если это происходит для последней записи журнала приложения.
Кроме того, пожалуйста, дайте мне знать, могу ли я реализовать то же самое, но с использованием новых ключевых слов C# 5.0 async
и await
с более чистым кодом. Я не против требовать .NET 4.5.
Заранее спасибо.