c# - .NET Core 2.2 中 Socket BeginConnect 同步执行回调
问题描述
我看到了一些意想不到的行为,虽然不一定会导致问题,但我想了解有关异步套接字编程的问题。
这是关于 mySocket.BeginConnect 调用的执行及其对提供的 AsyncCallback 的调用。使用一些用于网络通信的测试项目,我看到对于相同的代码,提供的回调有时会在 BeginConnect 执行期间被同步调用,有时会被异步调用(BeginConnect 在完成回调之前已经返回 IASyncResult),后一种情况是最常见的(80% - 90% 的案例)。
但是,我无法通过一个非常简单的测试用例来重现同步回调调用,该测试用例带有套接字 tcp 客户端和服务器通信,只是垃圾邮件连接/断开调用。
我查看了 .NET Core 2.2 框架的源代码,发现底层的 LazyAsyncResult 类有两个构造函数,其中一个在其构造函数中同步调用回调。但是,我没有发现框架使用该构造函数的任何情况。我使用调试器进行的调用似乎总是创建一个 ContextAwareResult,它只有一个对另一个构造函数的基本构造函数调用。在其中一些测试用例中,我还可以在调试器中清楚地看到 CompletedSynchronously 属性返回 true。
在哪种情况下同步调用此回调的任何提示以及为什么?
干杯。
编辑:
- 测试在 Windows 10 上进行。
- 完整框架 .NET 4.6.2 上完全相同的代码始终异步创建。
解决方案
您没有指定用于测试的操作系统,但假设它是 Windows 的情况(对于非 Windows,我很有信心地说行为应该相似)这是异步 I/O 操作的预期行为。特别是不能保证异步 I/O 请求总是异步完成。当 I/O 管理器可能出于明显的原因尝试缩短 I/O 操作路径时(很好的示例是快速 I/O 操作,它通过设备驱动程序绕过典型的 I/O 流并直接与内存管理器通信 - 这主要是为了可以兑现的文件操作)。在这种情况下,结果可以在同一个线程中返回,而不管操作是否被请求为异步。对于网络 I/O,这种行为最常见于读取操作(对于数据已经读入内部缓冲区的情况),而对于写入操作(对于 TCP,主要用于 Nagle 或延迟 ACK 在完成时打开的情况)输出操作不需要等待 ACK 数据包)。至于打开 TCP 连接的场景,当 TCP 握手过程省略网络层时,就像 SIO_LOOPBACK_FAST_PATH 选项的情况一样(请参阅此处和此处了解更多详细信息),但只能用于环回(本地主机)接口套接字。
.NET I/O 异步建立在本机 I/O 机制之上,并继承了这些机制的属性和行为。
推荐阅读
- razor - 为什么 Blazor Webassembly 应用程序中的每个 razor 页面导航都会出现“加载...”延迟?
- r - 需要从另一个 DataFrame 更新 R 中的 DataFrame,一个 DataFrame 的 colnames 与另一个 DataFrame 的内容匹配
- netsuite - 将自定义字段添加到付款、存款和退款 (NetSuite)
- discord.py - “RawReactionActionEvent”对象没有属性“作者”添加事件冷却时间的问题
- mongodb - 使用 $match 从具有相同键值的不同数组中查询
- postgresql - 在比较 postgres 和 timescaledb 之间的插入性能时,timescaledb 没有表现得那么好?
- flutter - 如何在颤动中从单例中删除共享首选项的数据?
- google-cloud-firestore - Firestore SecurityRules get () 问题
- azure-web-app-service - 在 Azure 上远程调试 Blazor WASM?
- java - java模块版本不匹配