Socket.End 方法不引发 ObjectDisposedException
如果套接字已关闭,System.Net.Sockets.Socket.End*
方法(例如,EndSend)会引发 SocketException 而不是 ObjectDisposedException。
旧行为
以前,受影响的方法针对关闭的套接字会引发 ObjectDisposedException。
新行为
从 .NET 7 开始,受影响的方法针对关闭的套接字会引发 SocketException,且 SocketErrorCode 设置为 SocketError.OperationAborted。
引入的版本
.NET 7
中断性变更的类型
此项更改可能会影响二进制兼容性。
更改原因
异步编程模型 (APM) API 即那些名为 Begin*
和 End*
的。 从 .NET 6 开始,这些旧版 API 通过基于 Task
的实现获得支持,这是出于统一和简化 Socket
代码库的需要。 但使用 6.0 实现时,TaskScheduler.UnobservedTaskException 上有时会引发意外事件。 即使 API 正确使用,也会发生这种情况,这意味着调用代码始终会调用 End*
方法,包括套接字已关闭时。
更改为引发 SocketException 是为了确保在这种情况下不会泄露任何未发现的异常。
建议的操作
如果代码从任何 Socket.End*
方法中捕获某个 ObjectDisposedException,请将其更改为捕获 SocketException 并引用 SocketException.SocketErrorCode 来调查其根本原因。
注意
即便套接字关闭,APM 代码也应始终确保在相应的 Begin*
方法之后调用 End*
方法。
受影响的 API
- System.Net.Sockets.Socket.EndConnect(IAsyncResult)
- System.Net.Sockets.Socket.EndDisconnect(IAsyncResult)
- System.Net.Sockets.Socket.EndSend
- System.Net.Sockets.Socket.EndSendFile(IAsyncResult)
- System.Net.Sockets.Socket.EndSendTo(IAsyncResult)
- System.Net.Sockets.Socket.EndReceive
- System.Net.Sockets.Socket.EndAccept