套接字BeginConnect .NET Core 2.2中同步执行回调

时间:2019-03-15 11:36:53

标签: c# sockets .net-core

我想了解一些有关异步套接字编程的意外行为,尽管不一定会引起问题。

这与mySocket.BeginConnect调用的执行及其对提供的AsyncCallback的调用有关。通过一些用于网络通信的测试项目,我看到对于相同的代码,提供的回调有时在BeginConnect执行期间被同步调用,有时被异步调用(BeginConnect在回调完成之前已经返回了IASyncResult),后一种情况是最常见的(80%-90%的情况)。

但是,我无法通过一个非常简单的测试用例通过套接字tcp客户端和服务器通信(只是垃圾邮件连接/断开连接)来重现同步回调调用。

我检查了.NET Core 2.2框架的源代码,发现基础LazyAsyncResult类具有两个构造函数,其中一个在其构造函数中同步调用回调。但是,我找不到框架使用该构造函数的任何情况。我在调试器中逐步执行的调用似乎总是创建一个ContextAwareResult,该ContextAwareResult仅具有对其他构造函数的基本构造函数调用。在某些测试案例中,我还可以在调试器中清楚地看到CompletedSynchronously属性返回true。

有什么提示可以在哪种情况下同步调用此回调,为什么?

干杯。

编辑:

  • 测试在Windows 10上进行。
  • 在完全框架.NET 4.6.2上完全相同的代码始终总是异步创建。

1 个答案:

答案 0 :(得分:0)

您尚未指定用于测试的操作系统,但假设它是Windows(对于非Windows,我非常自信地说该行为应该类似),这是异步I / O操作的预期行为。特别是不能保证异步I / O请求总是异步完成。如果有明显的原因,I / O管理器可能会尝试缩短I / O操作路径(很好的例子是快速I / O操作,它通过设备驱动程序绕过典型的I / O流并直接与内存管理器进行通信-这主要是为了可以兑现的文件操作)。在那种情况下,结果可以在同一线程中返回,而不管该操作被请求为异步的事实。对于网络I / O,读操作(在数据已经读入内部缓冲区的情况下)最常遇到此行为,写操作(在TCP完成后大多数情况下对于Nagle或延迟ACK开启的情况下,对于TCP操作更不常见)输出操作不需要等待ACK数据包)。对于打开TCP连接的情况,TCP握手过程可能会忽略网络层,例如SIO_LOOPBACK_FAST_PATH选项(有关更多详细信息,请参见herehere),但是该协议只能用于环回(本地主机)接口套接字。

.NET I / O异步建立在本机I / O机制的基础上,并继承了这些机制的属性和行为。