Являются ли Stream.ReadAsync и Stream.WriteAsync предположительно, чтобы изменить положение курсора синхронно перед возвратом или после завершения операции?

Я пытаюсь реализовать Stream, который поддерживает ReadAsync и WriteAsync, и с учетом запаздывания documentation, Я изо всех сил пытаюсь понять, как это сделать правильно. В частности, относительно позиции курсора потока. Аналогичный вопрос был задан здесь и здесь относительно старой функции BeginRead. Документация для этой функции, по-видимому, указывала на то, что BeginRead не следует вызывать снова до тех пор, пока не будут выполнены ожидающие асинхронные операции.

Учитывая, что BeginRead теперь устарело больше не рекомендуется для новой разработки и Stream имеет вероятность были значительно изменены для реализации новых функций Async, все еще неясно. (EDIT: Обычно этот вид предупреждения означает, что новые функции реализованы напрямую, а старые функции вызывают новые и остаются только для обратной совместимости, но это, похоже, не совсем так).

Функции ReadAsync и WriteAsync определены так, что они не принимают желаемую позицию потока чтения/записи в качестве Win32 counterparts делают (очень плохой выбор дизайна, на мой взгляд), но вместо этого полагаются на текущую позицию, связанную с реализацией потока. Эта ситуация прекрасна, если выполнено одно из двух условий:

  • ReadAsync и WriteAsync должны захватить текущую позицию курсора для использования этой операцией и обновить ее, как если бы операция была завершена (или вообще не обновлена) до того, как они вернут Task или
  • Вызов ReadAsync или WriteAsync невозможен, пока все предыдущие асинхронные вызовы не будут завершены.

За пределами этих двух условий вызывающий абонент никогда не может быть уверен в позиции чтения или записи, поскольку ожидающие асинхронные операции могут изменить положение потока между любыми Seek и вызвать ReadAsync или WriteAsync. Ни одно из этих условий не документировано как требование, поэтому мне остается задаться вопросом, как он должен функционировать.

Мое тестирование whitebox, по-видимому, указывает на то, что по крайней мере для версии FileStream Stream позиция потока обновляется асинхронно, что, как представляется, указывает на то, что второе условие (разрешено только одной ожидающей операции) требуется, но это кажется серьезным ограничением (это, безусловно, исключает любую внутреннюю реализацию сбора рассеяния).

Может ли кто-нибудь предоставить какую-либо авторитетную информацию относительно того, применяется ли прежнее ограничение BeginRead к ReadAsync или нет?

Ответ 1

Может ли кто-либо предоставить какую-либо авторитетную информацию относительно того, применяется ли прежнее ограничение BeginRead к ReadAsync или нет?

Те же ограничения применяются для BeginRead и ReadAsync.

Старые методы APM не устарели. Они все еще полностью поддерживаются, и нет ничего плохого в их использовании. Однако методы async значительно проще в использовании, поэтому в документации предлагается использовать их.

Все эти async "перегрузки" на этих старых классах обычно по-прежнему состоят из вызова BeginXXX и EndXXX или не более двух параметров вызывают общий метод (например, FileStream.BeginReadAsync). Я никогда не видел никакого кода (в рамках или иначе), у которого есть методы обертки APM над async.

Следовательно, вызов ReadAsync приведет к вызову BeginRead, поэтому любое ограничение применимо к обоим. Кроме того, поскольку Stream не является потокобезопасным и не рекламирует себя как совместимый с одновременным использованием (это немного отличается), можно с уверенностью предположить, что вы не можете наводнить его с помощью запросов async одновременно.