Stream.ReadAsync 和 Stream.WriteAsync 应该在返回之前或操作完成之后同步更改光标位置吗?

Are Stream.ReadAsync and Stream.WriteAsync supposed to alter the cursor position synchronously before returning or after the operation completes?

我一直在尝试实现支持 ReadAsyncWriteAsyncStream,考虑到 documentation, I'm struggling to understand how to do so properly. Specifically, with respect to the stream's cursor position. A similar question was asked here and here 对旧 BeginRead 的稀缺性] 功能。该函数的文档似乎表明 BeginRead 在任何挂起的异步操作完成之前不应再次调用。

鉴于 BeginRead 现在 已弃用 no longer recommended for new development 并且 Stream 可能已被显着改变以实现新的异步功能,事情是再次不清楚。 (编辑:通常这种警告意味着新函数被直接实现,旧函数调用新函数并且仍然存在只是为了向后兼容,但这里似乎并非如此)。

ReadAsyncWriteAsync 函数的定义使得它们不会像 Win32 counterparts 那样采用所需的 read/write 流位置(非常糟糕的设计选择在我看来),而是依赖于流实现的当前位置。如果满足以下两个条件之一,则这种情况很好:

  1. ReadAsyncWriteAsync 必须抓取当前光标位置供操作使用,并更新它,就好像操作在 return 之前完成(或根本不更新) Task
  2. 在所有先前的异步调用完成之前,无法调用 ReadAsyncWriteAsync

在这两个条件之外,调用者永远无法确定读取或写入将发生的位置,因为挂起的异步操作可能会改变任何 Seek 和调用 ReadAsyncWriteAsync。这些条件都没有记录为要求,所以我想知道它应该如何运作。

我的白盒测试似乎表明至少对于 StreamFileStream 版本,流位置更新是异步的,这似乎表明第二个条件(只允许一个挂起的操作) 仍然是必需的,但这似乎是一个严重的限制(它肯定排除了任何类型的内部分散 - 聚集实现)。

任何人都可以提供关于旧 BeginRead 限制是否仍然适用于 ReadAsync 的权威信息吗?

Can anyone provide any kind of authoritative information as to whether the old BeginRead limitation still applies to ReadAsync or not?

相同的限制适用于 BeginReadReadAsync

没有弃用旧的 APM 方法。它们仍然得到完全支持,使用它们没有任何问题。但是,async 方法更易于使用,因此文档建议改用它们。

这些旧 类 上的所有这些 async "overloads" 通常仍然包含调用 BeginXXXEndXXX 或最多两个选项都调用共享方法(例如 FileStream.BeginReadAsync)。我从未见过任何代码(在框架中或其他方面)在 async 之上具有 APM 包装器方法。

因此,calling ReadAsync will result in calling BeginRead 所以任何限制都适用于两者。此外,由于 Stream 不是线程安全的,也没有宣称是并发安全的(这略有不同),因此可以安全地假设您不能同时用 async 请求淹没它。