Есть ли блокировка StreamReader, TextReader или StringReader в .NET? - PullRequest
3 голосов
/ 30 октября 2008

Я хочу запустить фоновую задачу, которая читает входные данные из TextReader и обрабатывает их по очереди. Я хочу, чтобы фоновая задача блокировалась, пока пользователь не введет текст в поле и не нажмет кнопку «Отправить». Есть ли какая-то разновидность TextReader, которая будет блокировать, пока текст не станет доступным, и позволит вам каким-то образом добавить больше текста в основной источник?

Я думал, что StreamReader и StreamWriter, указывающие на один и тот же MemoryStream, могут работать, но, похоже, это не так. StreamReader видит, что MemoryStream в начале пуст, и никогда больше не проверяет.

Я понимаю, что было бы проще написать метод ProcessLine () и вызывать его всякий раз, когда пользователь нажимает кнопку отправки. Однако я пытаюсь спроектировать архитектуру плагинов и хочу, чтобы плагины выглядели как старомодные консольные приложения с входным потоком и выходным потоком. Я хочу, чтобы входной поток плагина просто блокировался до тех пор, пока пользователь не нажмет кнопку отправки с некоторым вводимым текстом.

Ответы [ 2 ]

5 голосов
/ 30 октября 2008

Кажется, что нет реализации этого - что странно, поскольку я согласен, что это будет полезная конструкция. Но это должно быть просто написать. Примерно так должно работать:

  public class BlockingStream: Stream
  {
    private readonly Stream _stream;

    public BlockingStream(Stream stream)
    {
      if(!stream.CanSeek)
        throw new ArgumentException("Stream must support seek", "stream");
      _stream = stream;
    }

    public override void Flush()
    {
      lock (_stream)
      {
        _stream.Flush();
        Monitor.Pulse(_stream);
      }
    }

    public override long Seek(long offset, SeekOrigin origin)
    {
      lock (_stream)
      {
        long res = _stream.Seek(offset, origin);
        Monitor.Pulse(_stream);
        return res;
      }
    }

    public override void SetLength(long value)
    {
      lock (_stream)
      {
        _stream.SetLength(value);
        Monitor.Pulse(_stream);
      }
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
      lock (_stream)
      {
        do
        {
          int read = _stream.Read(buffer, offset, count);
          if (read > 0)
            return read;
          Monitor.Wait(_stream);
        } while (true);
      }
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
      lock (_stream)
      {
        long currentPosition = _stream.Position;
        _stream.Position = _stream.Length;
        _stream.Write(buffer, offset, count);
        _stream.Position = currentPosition;
        Monitor.Pulse(_stream);
      }
    }

    public override bool CanRead
    {
      get
      {
        lock (_stream)
        {
          return _stream.CanRead;
        }
      }
    }

    public override bool CanSeek
    {
      get
      {
        lock (_stream)
        {
          return _stream.CanSeek;
        }
      }
    }

    public override bool CanWrite
    {
      get
      {
        lock (_stream)
        {
          return _stream.CanWrite;
        }
      }
    }

    public override long Length
    {
      get
      {
        lock (_stream)
        {
          return _stream.Length;
        }
      }
    }

    public override long Position
    {
      get
      {
        lock (_stream)
        {
          return _stream.Position;
        }
      }
      set
      {
        lock (_stream)
        {
          _stream.Position = value;
          Monitor.Pulse(_stream);
        }
      }
    }
  }
5 голосов
/ 30 октября 2008

Я думаю, вам было бы гораздо лучше создать событие в вашем главном приложении, которое вызывается, когда пользователь нажимает кнопку Отправить. Текстовые данные будут передаваться в аргументах события. Каждый плагин регистрирует обработчик события для события и обрабатывает данные, переданные при возникновении события. Это позволяет многим плагинам обрабатывать данные из одной отправки без большой работы по сантехнике с вашей стороны, и означает, что плагины могут бездействовать, пока не произойдет событие.

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