【发布时间】:2017-10-28 01:11:45
【问题描述】:
我正在实现自己的日志记录框架。以下是我的BaseLogger,它接收日志条目并将其推送到实现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。
提前致谢。
【问题讨论】:
-
啊……搞砸了。这里是午夜。我正在抓取这个并使用 NLog XD ...谢谢大家的帮助。
标签: c#-4.0 thread-safety task-parallel-library