Análisis fragmentado con FParsec
Pregunta
¿Es posible enviar entradas a un analizador FParsec en fragmentos, como desde un socket?Si no es así, ¿es posible recuperar el resultado actual y la parte no analizada de un flujo de entrada para poder lograrlo?Estoy intentando ejecutar los fragmentos de entrada que provienen de SocketAsyncEventArgs
sin almacenar mensajes completos en el buffer.
Actualizar
La razón para señalar el uso de SocketAsyncEventArgs
era para indicar que enviar datos a un CharStream
podría resultar en un acceso asincrónico al subyacente Stream
.Específicamente, estoy considerando usar un búfer circular para enviar los datos que ingresan desde el socket.Recuerdo la documentación de FParsec señalando que el subyacente Stream
No se debe acceder de forma asincrónica, por lo que había planeado controlar manualmente el análisis fragmentado.
Preguntas finales:
- ¿Puedo usar un amortiguador circular debajo de mi
Stream
pasó a laCharStream
? - ¿No necesito preocuparme por controlar manualmente la fragmentación en este escenario?
Solución
La versión normal de FParsec (aunque no la Versión de baja confianza) lee la entrada en fragmentos, o "en bloques", como lo llamo en el CharStream
documentación.Por lo tanto, si construyes un CharStream
a partir de una System.IO.Stream
y el contenido es lo suficientemente grande como para abarcar múltiples CharStream
bloques, puede comenzar a analizar antes de haber recuperado completamente la entrada.
Tenga en cuenta sin embargo, que el CharStream
consumirá el flujo de entrada en trozos de un tamaño fijo (pero configurable), es decirllamará al Read
método de la System.IO.Stream
tantas veces como sea necesario para llenar un bloque completo.Por lo tanto, si analiza la entrada más rápido de lo que puede recuperar la nueva entrada, el CharStream
puede bloquearse aunque ya haya alguna entrada sin analizar, porque todavía no hay suficiente entrada para llenar un bloque completo.
Actualizar
La(s) respuesta(s) a sus preguntas más importantes: 42.
¿Cómo implementas el
Stream
a partir del cual se construye elCharStream
Depende totalmente de usted.La restricción que recuerdas que excluye el acceso paralelo sólo se aplica alCharStream
clase, que no es segura para subprocesos.Implementando el
Stream
ya que un amortiguador circular probablemente restrinja la distancia máxima sobre la cual puede retroceder.El tamaño del bloque del
CharStream
influye en qué tan lejos puedes retroceder cuando elStream
no admite la búsqueda.La forma más sencilla de analizar la entrada de forma asíncrona es realizar el análisis en una tarea asíncrona (es decir,en un hilo de fondo).En la tarea, simplemente puede leer el socket de forma sincrónica o, si no confía en el almacenamiento en búfer del sistema operativo, puede usar una clase de transmisión como la
BlockingStream
descrito en el artículo que vinculó en el segundo comentario a continuación.Si la entrada se puede separar fácilmente en partes independientes (p. ej.líneas para un formato de texto basado en líneas), podría ser más eficiente fragmentarlo usted mismo y luego analizar la entrada fragmento por fragmento.