LoggerThread.cs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Threading;
  4. namespace Wayne.Lib.Log
  5. {
  6. internal class LoggerThread : IDisposable
  7. {
  8. #region Fields
  9. private readonly Thread thread;
  10. private readonly AutoResetEvent waitEvent;
  11. private readonly Queue<LogEntry> entryQueue = new Queue<LogEntry>();
  12. private readonly object entryQueueLock = new object();
  13. private readonly object logWritingLock = new object();
  14. private bool threadShouldExit; // Flag that is used to indicate to the thread that it should exit gracefully.
  15. private bool disposed;
  16. private readonly LogConfig logConfig;
  17. #endregion
  18. #region Construction & Finalizer
  19. /// <summary>
  20. /// Initializes a new instance of the Logger thread and starts it.
  21. /// </summary>
  22. /// <param name="logType"></param>
  23. /// <param name="logConfig"></param>
  24. public LoggerThread(LogType logType, LogConfig logConfig)
  25. {
  26. this.logConfig = logConfig;
  27. //Create the wait event
  28. waitEvent = new AutoResetEvent(false);
  29. //Create the thread.
  30. //thread = new Thread(Execute) { Priority = Logger.ThreadPriority };
  31. //switch (logType)
  32. //{
  33. // case LogType.Debug:
  34. // thread.Name = "Debug Logger thread";
  35. // break;
  36. // case LogType.Event:
  37. // thread.Name = "Event Logger thread";
  38. // break;
  39. //}
  40. //thread.IsBackground = Logger.ThreadPriority.IsIn(ThreadPriority.Lowest, ThreadPriority.BelowNormal);
  41. //thread.Start();
  42. }
  43. /// <summary>
  44. /// Finalizer
  45. /// </summary>
  46. ~LoggerThread()
  47. {
  48. Dispose(false);
  49. }
  50. #endregion
  51. #region IDisposable Members
  52. /// <summary>
  53. /// Disposes the resources owned by the logger thread.
  54. /// </summary>
  55. public void Dispose()
  56. {
  57. Dispose(true);
  58. GC.SuppressFinalize(this);
  59. }
  60. /// <summary>
  61. /// Internal dispose method.
  62. /// </summary>
  63. /// <param name="disposing"></param>
  64. private void Dispose(bool disposing)
  65. {
  66. if (!disposed)
  67. {
  68. disposed = true;
  69. if (disposing)
  70. {
  71. threadShouldExit = true;
  72. waitEvent.Set();
  73. waitEvent.Close();
  74. thread.Join();
  75. }
  76. }
  77. }
  78. #endregion
  79. #region The thread method
  80. /// <summary>
  81. /// The main function for the logger thread.
  82. /// </summary>
  83. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
  84. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")]
  85. private void Execute()
  86. {
  87. while (!threadShouldExit)
  88. {
  89. try
  90. {
  91. // Wait for an event.
  92. waitEvent.WaitOne();
  93. if (!disposed)
  94. {
  95. // Clear the entry queue.
  96. bool queueEmpty;
  97. do
  98. {
  99. // Pick the next logEntry in the queue safely in a locked way.
  100. LogEntry logEntry = null;
  101. lock (entryQueueLock)
  102. {
  103. if (entryQueue.Count > 0)
  104. logEntry = entryQueue.Dequeue();
  105. queueEmpty = (entryQueue.Count == 0);
  106. }
  107. // Was there a log entry for me?
  108. if (!disposed && (logEntry != null))
  109. PerformLog(logEntry);
  110. }
  111. while (!queueEmpty);
  112. }
  113. }
  114. catch (Exception exception)
  115. {
  116. //Logger.FireOnThreadException(new LogException(LogExceptionType.GeneralThreadException,
  117. // "An Exception is caught in the Logger.Execute() method. See inner exception!", exception));
  118. }
  119. #if WindowsCE
  120. catch
  121. {
  122. Logger.FireOnThreadException(new LogException(LogExceptionType.GeneralThreadException,
  123. "An unknown exception is caught in the Logger.Execute() method."));
  124. }
  125. #endif
  126. }
  127. }
  128. /// <summary>
  129. /// Performs the actual logging.
  130. /// </summary>
  131. /// <param name="logEntry"></param>
  132. private void PerformLog(LogEntry logEntry)
  133. {
  134. lock (logWritingLock)
  135. {
  136. UnregisterEntity unregisterEntity = logEntry as UnregisterEntity;
  137. if (unregisterEntity != null)
  138. {
  139. logConfig.UnregisterEntity(unregisterEntity.EntityCategory.Entity);
  140. return;
  141. }
  142. LogWriter[] logWriters;
  143. DebugMarkerLogEntry debugMarkerLogEntry = logEntry as DebugMarkerLogEntry;
  144. if (debugMarkerLogEntry != null)
  145. {
  146. // Get all active LogWriters.
  147. logWriters = logConfig.GetLogWriters();
  148. }
  149. else
  150. {
  151. // Get a list of the LogWriters that wants to log this entry.
  152. logWriters = logConfig.GetLogWriters(logEntry.EntityCategory);
  153. }
  154. // Call them in turn and write the log entry.
  155. foreach (LogWriter writer in logWriters)
  156. writer.Write(logEntry);
  157. }
  158. }
  159. #endregion
  160. #region Public Methods
  161. /// <summary>
  162. /// Adds an entry that should be handled by the logger thread.
  163. /// </summary>
  164. /// <param name="logEntry"></param>
  165. public void AddEntry(LogEntry logEntry)
  166. {
  167. if (disposed)
  168. return;
  169. //if (Logger.Synchronized)
  170. //{
  171. // PerformLog(logEntry);
  172. //}
  173. //else
  174. {
  175. lock (entryQueueLock)
  176. {
  177. entryQueue.Enqueue(logEntry);
  178. }
  179. waitEvent.Set();
  180. }
  181. }
  182. #endregion
  183. }
  184. }