【发布时间】:2017-01-11 04:56:09
【问题描述】:
我是 C# 编程的新手,只是为了学习,我想制作一个在低优先级后台线程上运行的异步应用程序记录器。我编写了一个记录器类,用作应用程序中任何其他类的接口,以创建新的日志条目。然后这个记录器简单地将它发送到一个日志调度器,然后它把它推送到一个 BlockingCollection
但是,我遇到的问题是,如果应用程序在退出之前请求日志条目,则永远不会写入日志。 LogDispatcher 的 Dispose 方法也永远不会被调用,因为该方法中的退出日志永远不会被写入。我不确定如何让后台线程在它终止之前完成整个阻塞集合,然后在父应用程序线程终止时调用 dispose 方法。这是代码。
public sealed class Logger : ILogger
{
// Fully lazy implementation for
// 1) learning purposes and
// 2) in case log disabling is a feature to be added in the future
private static readonly Lazy<Logger> L = new Lazy<Logger>(() => new Logger());
public static Logger Instance
{
get
{
return L.Value;
}
}
private double entryNumber = 0;
private int verbosity { get; set; }`private Logger()
{
this.verbosity = 3;
LogDispatcher.Instance.pushNewLog(new Log(
Log.LogType.Debug,
entryNumber++,
"LOG -- LogFile created with verbosity " + this.verbosity,
DateTime.Now.ToString("yyyy - mm - dd hh: mm:ss.fff")));
}
public void debug(string message)
{
if (this.verbosity > 2)
{
LogDispatcher.Instance.pushNewLog(new Log(
Log.LogType.Debug,
entryNumber++,
message,
DateTime.Now.ToString("yyyy-mm-dd hh:mm:ss.fff"
)));
}
}
public void warning(string warning)
{
if (this.verbosity > 1)
{
LogDispatcher.Instance.pushNewLog(new Log(
Log.LogType.Warning,
entryNumber++,
warning,
DateTime.Now.ToString("yyyy-mm-dd hh:mm:ss.fff"
)));
}
}
public void exception(string message, Exception e)
{
LogDispatcher.Instance.pushNewLog(new Log(
Log.LogType.Exception,
(entryNumber++),
message,
DateTime.Now.ToString("yyyy-mm-dd hh:mm:ss.fff"),
Thread.CurrentThread.ManagedThreadId,
e
));
}
dispatcher的代码如下
internal class LogDispatcher : IDisposable
{
private static readonly Lazy<LogDispatcher> LD = new Lazy<LogDispatcher>(() => new LogDispatcher());
private readonly StreamWriter LogFile;
private readonly BlockingCollection<Log> logQueue;
private Thread loggingThread;
private bool terminate = false;
public static LogDispatcher Instance
{
get
{
return LD.Value;
}
}private LogDispatcher()
{
// initialize the log folder
string logPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\NETLogger";
{
try
{
Directory.CreateDirectory(logPath);
}
catch (Exception e)
{
Console.WriteLine("An error occured while making the logfile.");
Console.WriteLine(e.ToString());
}
}
// now make logfile
try
{
this.LogFile = File.CreateText(logPath + "\\LogFile.txt");
this.LogFile.AutoFlush = true;
}
catch (Exception e)
{
Console.WriteLine("An error occured while opening LogFile.txt");
Console.WriteLine(e.ToString());
}
// make the blocking collection that stores all queued logs
this.logQueue = new BlockingCollection<Log>();
// initialize writer loggingThread to run in the background
this.loggingThread = new Thread(new ThreadStart(logWriter));
this.loggingThread.IsBackground = true;
this.loggingThread.Start();
}
public void logWriter()
{
Log writingLog = new Log();
while (!terminate && logQueue.Count != 0)
{
if (this.logQueue.TryTake(out writingLog, -1))
{
switch(writingLog.lType)
{
case (Log.LogType.Debug) :
LogFile.WriteLine(writingLog.entryNumber + " -- DEBUG -- " + writingLog.timeStamp);
LogFile.WriteLine("\t" + writingLog.message);
break;
case (Log.LogType.Warning) :
LogFile.WriteLine(writingLog.entryNumber + " -- WARNING -- " + writingLog.timeStamp);
LogFile.WriteLine("\t" + writingLog.message);
break;
case (Log.LogType.Exception) :
LogFile.WriteLine(writingLog.entryNumber + " -- EXCEPTION -- " + writingLog.timeStamp);
LogFile.WriteLine("\t ============== EXCEPTION INFORMATION FOLLOWS ============== ");
LogFile.WriteLine("\t Log Message : " + writingLog.message);
LogFile.WriteLine("\t Exception Message: " + writingLog.e.Message);
LogFile.WriteLine("\t Exception Thread :" + writingLog.threadId);
LogFile.WriteLine("\t Source: " + writingLog.e.ToString());
LogFile.WriteLine("\t=============== END EXCEPTION INFORMATION ================== ");
break;
}
}
}
}
public void pushNewLog(Log log)
{
logQueue.Add(log);
}
public void Dispose()
{
this.logQueue.Add(new Log(
Log.LogType.Debug,
-1,
"Terminating All Logging Procedures",
DateTime.Now.ToString("yyyy-mm-dd hh:mm:ss.fff")));
this.logQueue.CompleteAdding();
this.terminate = true;
this.loggingThread.Join();
}
~LogDispatcher()
{
this.Dispose();
}
【问题讨论】:
标签: c# .net multithreading logging