我正在实现我自己的日志框架。以下是我的BaseLogger
,它接收日志条目并将其推送到实现该abstract Log
方法的实际 Logger。
我使用 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.0async
和await
关键字以及更简洁的代码。我不介意需要 .NET 4.5。
提前致谢。