简体   繁体   English

为什么Stream.BeginRead()是同步的?

[英]Why is Stream.BeginRead() synchronous?

The Stream.BeginRead() takes a callback function as one of the parameters. Stream.BeginRead()将回调函数作为参数之一。 That callback function should be called asynchronously, but .net fakes that by calling callback function from the BeginRead() directly. 该回调函数应异步调用,但.net通过直接从BeginRead()调用回调函数来伪造该回调函数。 Why is that happening? 为什么会这样呢? It seems like there is no difference between Read() and BeginRead(). 似乎Read()和BeginRead()之间没有区别。
Please see the stack view below: 请查看下面的堆栈视图:

堆栈视图

As the documentation for Stream indicates: 正如Stream的文档所示:

The default implementation of BeginRead on a stream calls the Read method synchronously , which means that Read might block on some streams. 流的BeginRead的默认实现会同步调用Read方法 ,这意味着Read可能会在某些流上阻塞。 However, instances of classes such as FileStream and NetworkStream fully support asynchronous operations if the instances have been opened asynchronously. 但是,如果实例是异步打开的,则诸如FileStream和NetworkStream之类的实例完全支持异步操作。 Therefore, calls to BeginRead will not block on those streams. 因此,对BeginRead的调用不会在这些流上阻塞。 You can override BeginRead (by using async delegates, for example) to provide asynchronous behavior . 您可以重写BeginRead(例如,通过使用异步委托)以提供异步行为

In other words, it is up to each Stream sub-class to provide true asynchronous behavior. 换句话说,由每个Stream子类提供真正的异步行为。

Now, in the case of the ConnectStream you see in your stack trace, that's another .NET class (internal, undocumented) and it actually does provide an asynchronous implementation of BeginRead() . 现在,在的情况下ConnectStream您在堆栈跟踪看到,这是另一个.NET类(内部,无证),它实际上提供异步执行BeginRead() This can be seen in the source code . 可以在源代码中看到。 But, there's another important rule for asynchronous operations generally: asynchronous operations following the APM may in fact complete synchronously . 但是,异步操作通常还有另一个重要规则: 遵循APM的异步操作实际上可能是同步完成的 There's even a property on IAsyncResult to indicate this occurrence. IAsyncResult上甚至有一个属性来指示这种情况。

This in fact turns out to be the case for many asynchronous APIs. 实际上,许多异步API都是这种情况。 For example, when using await , it is possible that the method will not return at the await expression, but instead will retrieve the completion result immediately and just keep on executing in the current thread. 例如,当使用await ,该方法可能不会await表达式处返回,而是会立即检索完成结果,并继续在当前线程中执行。 This happens not only when the awaitable is just a synchronous operation dressed up in an asynchronous wrapper, but also when what would normally be an asynchronous operation can in fact be completed synchronously. 这不仅发生在等待的对象只是异步包装中的同步操作,而且实际上通常可以异步完成的异步操作也是如此。


I'm sure that if you were to check the IAsyncResult.CompletedSynchronously property in your callback, you would find it was set to true , as it's supposed to be when the API completes an asynchronous operation synchronously. 我确定如果您要检查回调中的IAsyncResult.CompletedSynchronously属性,您会发现它设置为true ,因为它应该是在API同步完成异步操作时实现的。 That property exists primarily for this very scenario, in case your own code needs to distinguish between operations that complete asynchronously and those that complete synchronously (in general, it shouldn't, but we all know code isn't always as it should be, and even sometimes can't be :) ). 该属性主要在这种情况下存在,以防万一您自己的代码需要区分异步完成的操作和同步完成的操作(通常不应该这样做,但是我们都知道代码并不总是应该如此,甚至有时不能是:))。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM