Threading и SOLID принцип - PullRequest
       9

Threading и SOLID принцип

2 голосов
/ 29 марта 2012

У меня есть следующий код настройки

public interface ILogger
{
  void WriteData(string Data);
}

public class Logger : ILogger
{
  public void WriteData(string Data)
  {
     //Write to disk   
  }
}

public interface ILogic
{
  void ProcessData(string Data);
}

public class Logic : ILogic
{
  private ILogger Logger;

  public Logic(ILogger Logger)
  {
    this.Logger = Logger;
  }

  public void ProcessData(string Data)
  {
     //Do stuff
     Logger.WriteData("Data to write");
  }
}

public class MainEntryPointClass
{
     private BlockingCollection<string> DataInCollection;
     private Task DataInTask;
     private CancellationTokenSource CancellationTokenSource;

     public Start()
     {
        InitializeDataIn();
     }

        private void InitializeDataIn()
        {
            CancellationTokenSource = new CancellationTokenSource();
            DataInCollection = new BlockingCollection<DataInContents>();
            DataInTask = Task.Factory.StartNew(() => ProcessDataIn(CancellationTokenSource.Token));
        }

      private void ProcessDataIn(CancellationToken CancelToken)
        {
            while (!CancelToken.IsCancellationRequested)
            {
                foreach (var item in DataInCollection.GetConsumingEnumerable())
                {
                    Logic.ProcessData(item);
                }
            }

        }
}

Итак, я создаю новую задачу в своем основном классе, а затем данные добавляются в DataInCollection, чтобы ставить в очередь данные по мере их поступления, мы говорим каждые 30 мс или около того. Это успешно обрабатывается.

Теперь я хочу записать данные в файл в отдельном потоке, чтобы в случае проблем с диском основная проверка логики не затрагивалась. Если есть проблема с диском, то логика может продолжаться. Я просто не уверен, где я делаю запись файла в отдельном потоке? Это класс Main, класс Logic или класс Logger?

Ответы [ 2 ]

3 голосов
/ 29 марта 2012

Logger несет ответственность за то, чтобы не блокировать абонента. Для этого можно использовать много разных стратегий. Вы не хотите превращать эти стратегии в класс, который их использует.

Я бы помещал сообщение в BlockingCollection<T>, и один поток ввода-вывода записывал его на диск.

Я также рекомендую имитировать существующий интерфейс ведения журнала, например, Common.Logging ILog, чтобы вы могли легко переключиться на существующую среду ведения журнала, если ваши требования «без сторонних разработчиков» когда-либо будут отменены. *

Что-то вроде:

class AsyncLogger:ILogger
{
  public AsyncLogger(ILogger backingLogger)
  {
    new Thread(()=>
      {
        while(true)
        {
          var data=_queue.Take();
          _backingLogger.WriteData(data);
        }
      }
    ).Start();
  }

  public void WriteData(string data)
  {
     _queue.Enqueue(data);
  }
}

(я пропустил такие вещи, как условие завершения для потока ввода-вывода, поля, обработка нескольких регистраторов, ...)

1 голос
/ 29 марта 2012

Надеемся, что за регистрацию отвечает класс Logger.Похоже, это правильное место для записи входящих данных на диск.

...