Фрагментированный синтаксический анализ с помощью FParsec
Вопрос
Можно ли отправлять входные данные в анализатор FParsec порциями, как из сокета?Если нет, возможно ли получить текущий результат и нераспределенную часть входного потока, чтобы я мог выполнить это?Я пытаюсь запустить фрагменты входных данных, поступающих из SocketAsyncEventArgs
без буферизации целых сообщений.
Обновить
Причина, по которой следует отметить использование SocketAsyncEventArgs
должен был обозначать, что отправка данных в CharStream
может привести к асинхронному доступу к базовому Stream
.В частности, я рассматриваю возможность использования циклического буфера для передачи данных, поступающих из сокета.Я помню, что в документации FParsec отмечалось, что лежащий в основе Stream
доступ к нему не должен осуществляться асинхронно, поэтому я планировал вручную управлять фрагментированным синтаксическим анализом.
Окончательные вопросы:
- Могу ли я использовать кольцевой буфер под моим
Stream
переданный вCharStream
? - Разве мне не нужно беспокоиться о ручном управлении разделением на фрагменты в этом сценарии?
Решение
Обычная версия FParsec (хотя и не Версия с низким уровнем доверия) считывает входные данные по частям, или "по блокам", как я называю это в CharStream
Документация.Таким образом, если вы построите CharStream
из System.IO.Stream
и контент достаточно велик, чтобы охватить несколько CharStream
блоки, вы можете начать синтаксический анализ до того, как полностью восстановите входные данные.
Однако обратите внимание, что CharStream
будет потреблять входной поток порциями фиксированного (но настраиваемого) размера, т.е.это вызовет Read
способ проведения System.IO.Stream
так часто, как это необходимо для заполнения всего блока.Следовательно, если вы проанализируете входные данные быстрее, чем сможете получить новые входные данные, то CharStream
может блокироваться, даже если уже есть какой-то нераспределенный ввод, потому что ввода еще недостаточно для заполнения полного блока.
Обновить
Ответы на ваши основные вопросы: 42.
Как вы реализуете
Stream
из которого вы строитеCharStream
это полностью зависит от вас.Ограничение, которое, как вы помните, исключает параллельный доступ, применимо только кCharStream
класс, который не является потокобезопасным.Реализуя
Stream
поскольку циклический буфер, скорее всего, будет ограничьте максимальное расстояние, на которое вы можете вернуться назад.Размер блока в
CharStream
влияет на то, как далеко вы можете вернуться назад, когдаStream
не поддерживает поиск.Самый простой способ асинхронного анализа входных данных - выполнить синтаксический анализ в асинхронной задаче (т. е.в фоновом потоке).В задаче вы могли бы просто синхронно прочитать сокет, или, если вы не доверяете буферизации ОС, вы могли бы использовать класс stream, такой как
BlockingStream
описано в статье, на которую вы ссылаетесь во втором комментарии ниже.Если входные данные могут быть легко разделены на независимые блоки (например,строк для текстового формата на основе строк), возможно, было бы эффективнее разбить его на части самостоятельно, а затем анализировать входной фрагмент за фрагментом.