3

TextReader から入力を読み取り、一度に 1 行ずつ処理するバックグラウンド タスクを実行したいと考えています。ユーザーがフィールドにテキストを入力して送信ボタンをクリックするまで、バックグラウンド タスクをブロックしたい。テキストが利用可能になるまでブロックし、基礎となるソースに何らかの方法でテキストを追加できる TextReader のフレーバーはありますか?

同じ MemoryStream を指す StreamReader と StreamWriter が機能する可能性があると考えましたが、機能していないようです。StreamReader は、MemoryStream が最初に空であることを認識し、再度チェックすることはありません。

ProcessLine() メソッドを作成して、ユーザーが送信ボタンをクリックするたびに呼び出す方が簡単だと思います。ただし、プラグイン アーキテクチャを設計しようとしており、入力ストリームと出力ストリームを備えた昔ながらのコンソール アプリのように見えるプラグインが必要です。ユーザーが入力テキストで送信ボタンをクリックするまで、プラグインの入力ストリームをブロックするだけです。

4

2 に答える 2

6

これは実装されていないようです - これは奇妙です. しかし、書くのは簡単であるべきです。このようなものが動作するはずです:

  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);
        }
      }
    }
  }
于 2008-10-29T22:48:46.347 に答える
5

ユーザーが[送信]をクリックしたときに発生するイベントをメインアプリケーションで作成する方がはるかに良いと思います。テキストデータはイベント引数で渡されます。各プラグインは、イベントのイベントハンドラーを登録し、イベントが発生したときに渡されるデータを処理します。これにより、多くのプラグインが1回の送信からのデータを処理でき、多くの配管作業を行う必要がなくなります。つまり、プラグインは、イベントが発生するまでアイドル状態のままでいることができます。

于 2008-10-29T21:50:15.500 に答える