我正在實現我自己的日誌框架。以下是我的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 ...感謝大家的幫助。 – Madushan