Последовательное логирование в отдельном потоке
Ещё одна доработка исходников:
Разгрузка основного потока от логирования.
Возможность изоляции от системных ресурсов, связанных с логированием.
Код
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
Беда какая-то с описанием темы. Ломается.