Здесь я снова с вопросами о многопоточности и упражнении по моему параллельному программированию класс.
У меня есть многопоточный сервер - реализованный с использованием .NET Модель асинхронного программирования - с GET
( загрузка ) и PUT
( загрузка ) файловые сервисы. Эта часть сделана и проверена.
Бывает, что в заявлении о проблеме говорится, что этот сервер должен иметь активность logging с минимальным влиянием на время отклика сервера, и это должно поддерживаться низким приоритетом thread - поток логгера - создан для этого эффекта. Все протоколирование сообщения должны быть переданы потоками , которые производят их этому протоколирующему потоку , с использованием механизма связи, который не может заблокировать thread , который вызывает его (помимо необходимой блокировки для обеспечения взаимного исключения) и предполагая, что некоторые сообщения регистрации могут быть проигнорированы.
Вот мое текущее решение, пожалуйста, помогите проверить, является ли это решением указанной проблемы:
using System;
using System.IO;
using System.Threading;
// Multi-threaded Logger
public class Logger {
// textwriter to use as logging output
protected readonly TextWriter _output;
// logger thread
protected Thread _loggerThread;
// logger thread wait timeout
protected int _timeOut = 500; //500ms
// amount of log requests attended
protected volatile int reqNr = 0;
// logging queue
protected readonly object[] _queue;
protected struct LogObj {
public DateTime _start;
public string _msg;
public LogObj(string msg) {
_start = DateTime.Now;
_msg = msg;
}
public LogObj(DateTime start, string msg) {
_start = start;
_msg = msg;
}
public override string ToString() {
return String.Format("{0}: {1}", _start, _msg);
}
}
public Logger(int dimension,TextWriter output) {
/// initialize queue with parameterized dimension
this._queue = new object[dimension];
// initialize logging output
this._output = output;
// initialize logger thread
Start();
}
public Logger() {
// initialize queue with 10 positions
this._queue = new object[10];
// initialize logging output to use console output
this._output = Console.Out;
// initialize logger thread
Start();
}
public void Log(string msg) {
lock (this) {
for (int i = 0; i < _queue.Length; i++) {
// seek for the first available position on queue
if (_queue[i] == null) {
// insert pending log into queue position
_queue[i] = new LogObj(DateTime.Now, msg);
// notify logger thread for a pending log on the queue
Monitor.Pulse(this);
break;
}
// if there aren't any available positions on logging queue, this
// log is not considered and the thread returns
}
}
}
public void GetLog() {
lock (this) {
while(true) {
for (int i = 0; i < _queue.Length; i++) {
// seek all occupied positions on queue (those who have logs)
if (_queue[i] != null) {
// log
LogObj obj = (LogObj)_queue[i];
// makes this position available
_queue[i] = null;
// print log into output stream
_output.WriteLine(String.Format("[Thread #{0} | {1}ms] {2}",
Thread.CurrentThread.ManagedThreadId,
DateTime.Now.Subtract(obj._start).TotalMilliseconds,
obj.ToString()));
}
}
// after printing all pending log's (or if there aren't any pending log's),
// the thread waits until another log arrives
//Monitor.Wait(this, _timeOut);
Monitor.Wait(this);
}
}
}
// Starts logger thread activity
public void Start() {
// Create the thread object, passing in the Logger.Start method
// via a ThreadStart delegate. This does not start the thread.
_loggerThread = new Thread(this.GetLog);
_loggerThread.Priority = ThreadPriority.Lowest;
_loggerThread.Start();
}
// Stops logger thread activity
public void Stop() {
_loggerThread.Abort();
_loggerThread = null;
}
// Increments number of attended log requests
public void IncReq() { reqNr++; }
}
В основном, вот основные пункты этого кода:
- Запуск низкоприоритетного потока , который зацикливает очередь журналов и печатает ожидающие журналы на выходе. После этого поток приостанавливается до поступления нового log ;
- Когда приходит журнал, поток регистратора пробуждается и выполняет свою работу.
Является ли это решение поточно-безопасным ? Я читал Производители-потребители Проблема и алгоритм решения, но в этой задаче, хотя у меня несколько производителей, у меня только один читатель.
Заранее спасибо за все ваше внимание.