Pregunta

Quiero ejecutar una tarea en segundo plano que lee la entrada de un TextReader y la procesa una línea a la vez. Quiero que la tarea en segundo plano se bloquee hasta que el usuario escriba texto en un campo y haga clic en el botón Enviar. ¿Hay algún tipo de TextReader que se bloquee hasta que el texto esté disponible y te permita agregar más texto a la fuente subyacente?

Pensé que un StreamReader y un StreamWriter que apuntan al mismo MemoryStream podrían funcionar, pero no lo parece. El StreamReader ve que el MemoryStream está vacío al principio y nunca lo vuelve a comprobar.

Me doy cuenta de que sería más fácil escribir un método ProcessLine () y llamarlo cada vez que el usuario haga clic en el botón de envío. Sin embargo, estoy tratando de diseñar una arquitectura de plug-in, y me gustaría que los plug-ins se vieran como aplicaciones de consola antiguas con un flujo de entrada y un flujo de salida. Quiero que la secuencia de entrada del complemento se bloquee hasta que el usuario haga clic en el botón de envío con algún texto de entrada.

¿Fue útil?

Solución

Parece que no hay una implementación de esto, lo cual es extraño, ya que estoy de acuerdo en que sería una construcción útil. Pero debería ser fácil de escribir. Algo como esto debería funcionar:

  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);
        }
      }
    }
  }

Otros consejos

Creo que estarías mucho mejor creando un evento en tu aplicación principal que se genera cuando el usuario pulsa Enviar. Los datos de texto se pasarían en el evento args. Cada complemento registra un controlador de eventos para el evento y maneja los datos que se pasan cuando se genera el evento. Esto permite que muchos complementos procesen los datos de un solo envío sin mucho trabajo de plomería de su parte, y significa que los complementos solo pueden quedar inactivos hasta que se levante el evento.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top