Последовательное логирование в отдельном потоке

Последовательное логирование в отдельном потоке
Atom
17.02.2013
VassilSanych


Ещё одна доработка исходников: Разгрузка основного потока от логирования. Возможность изоляции от системных ресурсов, связанных с логированием.

public abstract class BaseLogReceiver<TParent> : BaseLogSource<TParent>, ILogReceiver
	{
		/// <summary>
		/// Инициализировать <see cref="BaseLogReceiver{TParent}"/>.
		/// </summary>
		protected BaseLogReceiver()
		{
		}

		void ILogReceiver.AddLog(LogMessage message)
		{
			LoggingQueue.AddLogAction(()=>RaiseLog(message));
		}
	}


	/// <summary>
	///  Логирование в отдельном параллельном потоке
	/// </summary>
	public class LoggingQueue
	{
		//если понадобится подменять реализацию
		public static LoggingQueue Instance { get; set; }


		static LoggingQueue()
		{
			Instance = new LoggingQueue();
		}


		public LoggingQueue()
		{
			StartThread();
		}


		/// <summary>
		///  Запуск отдельного параллельного потока логирования
		/// </summary>
		protected virtual void StartThread()
		{
			_loggingQueue = new ConcurrentQueue<Action>();
			_waitLog = new AutoResetEvent(false);
			Task.Run(() => DoLoggingListen());
		}


		private ConcurrentQueue<Action> _loggingQueue;
		private AutoResetEvent _waitLog;


		/// <summary>
		///		Добавление записи в лог
		/// </summary>
		/// <param name="action"></param>
		public static void AddLogAction(Action action)
		{
			Instance.AddAction(action);
		}


		/// <summary>
		///  Добавление действия записи в лог в очередь потока логирования
		/// </summary>
		/// <param name="action"></param>
		public virtual void AddAction(Action action)
		{
			_loggingQueue.Enqueue(action);
			_waitLog.Set();
		}


		/// <summary>
		///  Чтение очереди действий логирования
		/// </summary>
		protected virtual void DoLoggingListen()
		{
			do
			{
				Action logAction;
				if (_loggingQueue.TryDequeue(out logAction))
					logAction.Invoke();
				else
					_waitLog.WaitOne();
			} while (!_stopped);
		}

		private bool _stopped;
		/// <summary>
		///  Создание условий окончания работы прослушивания очереди
		/// </summary>
		public virtual void Stop()
		{
			_stopped = true;
			_waitLog.Set();
		}

	}


	/// <summary>
	///  Затычка логирования (может понадобиться для тестирования)
	/// </summary>
	public class LoggingQueueMock: LoggingQueue
	{
		//protected override void DoLoggingListen()
		//{
		//}

		public override void AddAction(Action action)
		{
		}

		protected override void StartThread()
		{
		}
	}

Кстати, можно что-то придумать и для затыкания LoggingHelper.Now. Потому что привязка кода к ресурсам системного времени - это совсем не TDD.

Критика просто жизненно необходима :)

PS Беда какая-то с описанием темы. Ломается.


Теги:


Спасибо:


< 1 2 
VassilSanych

Фотография
Дата: 18.02.2013
Ответить


pyhta4og: Это было сделано для того, чтобы очередь не отжирала всю память. Это понятно. Вызов я не отменил, а заменил его пинанием таймера. pyhta4og: Помимо этого есть режим MaxMessages=-1 когда логирование идет синхронно. Это сделано для того чтобы производить отладку. Иначе получится что вы уже на бреакпойнт в коде робота встали, а логи еще в файл не записались. Для отладки нужно не костыли городить, а, например, сделать класс-заглушку, которая будет писать, куда надо и как надо, или просто сделать явный ключ bool OneThread.

Спасибо:
< 1 2 

Добавить файлы через драг-н-дроп, , или вставить из буфера обмена.

loading
clippy