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

C# Stream.ReadAsync和Stream.WriteAsync应该在返回之前或操作完成之后同步更改光标位置吗?,c#,stream,async-await,filestream,c#-5.0,C#,Stream,Async Await,Filestream,C# 5.0,我一直在尝试实现一个支持ReadAsync和WriteAsync的Stream,并且考虑到的稀疏性,我很难理解如何正确地做到这一点。具体而言,相对于流的光标位置。提出了一个类似的问题,关于旧的BeginRead函数。该函数的文档似乎表明,在任何挂起的异步操作完成之前,不应再次调用BeginRead 考虑到BeginRead现在已被弃用,而且Stream可能已被显著修改以实现新的异步函数,情况再次变得不明朗。(编辑:通常这种警告意味着直接实现新函数,旧函数调用新函数,只是为了向后兼容而仍然存在,但

我一直在尝试实现一个支持
ReadAsync
WriteAsync
Stream
,并且考虑到的稀疏性,我很难理解如何正确地做到这一点。具体而言,相对于流的光标位置。提出了一个类似的问题,关于旧的
BeginRead
函数。该函数的文档似乎表明,在任何挂起的异步操作完成之前,不应再次调用
BeginRead

考虑到
BeginRead
现在已被弃用,而且
Stream
可能已被显著修改以实现新的异步函数,情况再次变得不明朗。(编辑:通常这种警告意味着直接实现新函数,旧函数调用新函数,只是为了向后兼容而仍然存在,但这里的情况似乎不是这样)

ReadAsync
WriteAsync
函数的定义使得它们不会像它们所做的那样选择所需的读/写流位置(我认为这是一个非常糟糕的设计选择),而是依赖于流实现所保持的当前位置。如果满足以下两个条件之一,则该情况可以:

  • ReadAsync
    WriteAsync
    必须获取当前光标位置供操作使用,并在返回
    任务之前将其更新为操作已完成(或根本不更新),或者
  • 在以前的所有异步调用完成之前,不能调用
    ReadAsync
    WriteAsync
  • 在这两种情况之外,调用方永远无法确定读或写操作将发生在哪个位置,因为挂起的异步操作可能会在任何
    Seek
    和调用
    ReadAsync
    WriteAsync
    之间改变流的位置。这两个条件都没有被记录为需求,所以我想知道它应该如何工作

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

    是否有人能提供任何权威信息,说明旧的
    BeginRead
    限制是否仍然适用于
    ReadAsync

    是否有人能提供任何权威信息,说明旧的
    BeginRead
    限制是否仍然适用于
    ReadAsync

    同样的限制也适用于
    BeginRead
    ReadAsync

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

    所有这些
    async
    “重载”在这些旧类上通常仍然包括调用
    BeginXXX
    EndXXX
    ,或者最多这两个选项都调用一个共享方法(例如)。我从未见过任何代码(在框架中或其他地方)在
    async
    上有APM包装方法


    因此,任何限制都适用于这两者。此外,因为
    不是线程安全的,也不是作为并发安全的(这略有不同)可以安全地假设您不能并发地向它发送
    async
    请求。

    我认为设计背后的逻辑是,从本质上讲,流不是线程安全的;因此,在异步操作进行时访问流是没有意义的(仅仅因为该操作是异步的,允许您的代码在不阻塞的情况下优雅地等待流读/写,并不意味着在该操作进行期间使用来自另一个线程的流是一个好主意)。鉴于
    ReadAsync
    将读取未知数量的字节,它如何可能在操作完成之前准确地更新位置?并发IOs,即使按顺序启动,也可能导致回调被并发调用。这是大多数流实现的竞争条件。因此,在gen中不允许这样做eral.@Damien_The_unsiver:说得好。我主要考虑的是文件流,它总是有可能的,但对于大多数其他流,你是绝对正确的。在没有文档的情况下,我希望源代码中至少有一条注释指出这一限制,但我想对原始源代码w我必须满足。谢谢!我很喜欢2023行函数中的这句话:
    这段代码需要修复。