Вопрос

Кто-нибудь знает о реализации ленивого потока в .net?IOW, я хочу создать такой метод:

public Stream MyMethod() {
    return new LazyStream(...whatever parameters..., delegate() {
        ... some callback code.
    });
}

и когда мой другой код вызывает MyMethod(), чтобы вернуть поток, он фактически не будет выполнять никакой работы, пока кто-то действительно не попытается прочитать из потока.Обычным способом было бы заставить MyMethod принимать параметр потока в качестве параметра, но в моем случае это не сработает (я хочу передать возвращенный поток в MVC FileStreamResult).

Чтобы объяснить дальше, я хочу создать многоуровневую серию преобразований, поэтому

Набор результатов базы данных =(преобразован в)=> поток байтов =(привязан к)=> GZipStream =(передан в)=> конструктор FileStreamResult.

Набор результатов может быть огромным (ГБ), поэтому я не хочу кэшировать результат в MemoryStream, который можно передать конструктору GZipStream.Скорее, я хочу получить данные из набора результатов, когда GZipStream запрашивает данные.

Это было полезно?

Решение

Этот ответ (https://stackoverflow.com/a/22048857/1037948) ссылки на Эта статья о том, как написать свой собственный класс потока.

Цитирую ответ:

Производитель записывает данные в поток, а потребитель читает.В середине есть буфер, чтобы продюсер мог немного «записать вперед».Вы можете определить размер буфера.

Цитирую первоисточник:

Вы можете думать о ProducerConsumerStream как об очереди с интерфейсом Stream.Внутри он реализован как кольцевой буфер.Два индекса отслеживают точки вставки и удаления в буфере.Байты записываются по индексу Head и удаляются из индекса Tail.

Если Head переходит в Tail, то буфер заполнен, и производителю приходится ждать, пока прочитаются несколько байтов, прежде чем он сможет продолжить запись.Аналогично, если Tail догоняет Head, потребителю придется дождаться записи байтов, прежде чем он сможет продолжить работу.

Далее в статье описываются некоторые странные случаи, когда указатели оборачиваются, с полными примерами кода.

Другие советы

Большинство реализаций потоков по своей природе являются ленивыми потоками.Как правило, любой поток не будет считывать информацию из своего источника до тех пор, пока она не будет запрошена пользователем потока (кроме некоторого дополнительного «избыточного чтения», позволяющего выполнить буферизацию, что значительно ускоряет использование потока).

Было бы довольно легко создать реализацию Stream, которая не выполняла бы чтение до тех пор, пока это не понадобится, переопределив Читать чтобы открыть базовый ресурс и затем прочитать его при использовании, если вам нужна реализация полностью ленивого потока.Просто переопределите Read, CanRead, CanWrite и CanSeek.

В вашем классе Stream вам необходимо реализовать несколько методов System.IO.Stream, включая метод Read.

Что вы будете делать в этом методе, зависит от вас.Если вы решите вызвать делегат — это тоже ваше дело, и, конечно, вы можете передать этот делегат как один из параметров вашего конструктора.По крайней мере, я бы сделал это именно так.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top