C# 为什么Stream.beginhead()是同步的?

C# 为什么Stream.beginhead()是同步的?,c#,C#,BeginRead()将回调函数作为参数之一。该回调函数应该异步调用,但是.net通过直接从BeginRead()调用回调函数来伪造它。为什么会这样?看起来Read()和BeginRead()之间没有区别。 请参见下面的堆栈视图: 如图所示: 流上BeginRead的默认实现同步调用Read方法,这意味着Read可能会阻塞某些流。但是,如果已异步打开实例,则类的实例(如FileStream和NetworkStream)完全支持异步操作。因此,对BeginRead的调用不会阻塞这些流您可以覆盖Be

BeginRead()将回调函数作为参数之一。该回调函数应该异步调用,但是.net通过直接从BeginRead()调用回调函数来伪造它。为什么会这样?看起来Read()和BeginRead()之间没有区别。
请参见下面的堆栈视图:

如图所示:

流上BeginRead的默认实现同步调用Read方法,这意味着Read可能会阻塞某些流。但是,如果已异步打开实例,则类的实例(如FileStream和NetworkStream)完全支持异步操作。因此,对BeginRead的调用不会阻塞这些流您可以覆盖BeginRead(例如,通过使用异步委托)以提供异步行为

换句话说,由每个
子类提供真正的异步行为

现在,在堆栈跟踪中看到的
ConnectStream
的情况下,这是另一个.NET类(内部的,未文档化的),它实际上提供了
BeginRead()
的异步实现。这可以从中看出。但是,异步操作通常还有另一条重要规则:后面的异步操作实际上可能同步完成。甚至没有证据表明发生了这种情况

事实证明,许多异步API都是如此。例如,当使用
await
时,该方法可能不会在
await
表达式处返回,而是立即检索完成结果并继续在当前线程中执行。这不仅发生在等待操作只是一个用异步包装器包装的同步操作时,而且发生在通常是异步操作的操作实际上可以同步完成时


我确信,如果您要检查回调中的
IAsyncResult.CompletedSynchronously
属性,您会发现它被设置为
true
,就像API同步完成异步操作时应该设置的那样。该属性主要针对这个场景,以防您自己的代码需要区分异步完成的操作和同步完成的操作(通常不应该,但我们都知道代码并不总是应该的,有时甚至不能:)。

如图所示:

流上BeginRead的默认实现同步调用Read方法,这意味着Read可能会阻塞某些流。但是,如果已异步打开实例,则类的实例(如FileStream和NetworkStream)完全支持异步操作。因此,对BeginRead的调用不会阻塞这些流您可以覆盖BeginRead(例如,通过使用异步委托)以提供异步行为

换句话说,由每个
子类提供真正的异步行为

现在,在堆栈跟踪中看到的
ConnectStream
的情况下,这是另一个.NET类(内部的,未文档化的),它实际上提供了
BeginRead()
的异步实现。这可以从中看出。但是,异步操作通常还有另一条重要规则:后面的异步操作实际上可能同步完成。甚至没有证据表明发生了这种情况

事实证明,许多异步API都是如此。例如,当使用
await
时,该方法可能不会在
await
表达式处返回,而是立即检索完成结果并继续在当前线程中执行。这不仅发生在等待操作只是一个用异步包装器包装的同步操作时,而且发生在通常是异步操作的操作实际上可以同步完成时



我确信,如果您要检查回调中的
IAsyncResult.CompletedSynchronously
属性,您会发现它被设置为
true
,就像API同步完成异步操作时应该设置的那样。该属性主要针对这个场景,以防您自己的代码需要区分异步完成的操作和同步完成的操作(通常不应该,但我们都知道代码并不总是应该的,甚至有时不能:)。

假设有立即可用的数据,为什么不希望它同步地回叫您呢?fwiw,documentation()在base
Stream.BeginRead()
implementation.IIRC上调用此行为默认的流实现将所有异步调用传递给同步方法。由子类的实现者提供异步方法实现。默认情况下,它们不会变戏法。您正在使用的流实现可能没有APM方法的实现。默认情况下,基于任务的方法使用APM方法。@spender您的注释似乎是答案:)。假设立即有数据可用,为什么不让它同步地回叫您?fwiw,documentation()在base
Stream.beginhead()上调用此行为
implementation.IIRC默认流实现将所有异步调用传递给同步方法。由子类的实现者提供异步方法实现。默认情况下,它们不会变戏法。您正在使用的流实现可能没有APM方法的实现。基于任务的方法默认使用APM方法。@请使用命令