Socket.End methods don't throw ObjectDisposedException
System.Net.Sockets.Socket.End*
methods (for example, EndSend) throw a SocketException instead of an ObjectDisposedException if the socket is closed.
Previous behavior
Previously, the affected methods threw an ObjectDisposedException for closed sockets.
New behavior
Starting in .NET 7, the affected methods throw a SocketException with SocketErrorCode set to SocketError.OperationAborted for closed sockets.
Version introduced
.NET 7
Type of breaking change
This change can affect binary compatibility.
Reason for change
The asynchronous programming model (APM) APIs are those named Begin*
and End*
. Starting with .NET 6, these legacy APIs are backed with a Task
-based implementation as part of an effort to consolidate and simplify the Socket
codebase. Unfortunately, with the 6.0 implementation, unexpected events were sometimes raised on TaskScheduler.UnobservedTaskException. This happened even when the APIs were used correctly, meaning that the calling code always invoked the End*
methods, including when the socket was closed.
The change to throw a SocketException was made to ensure that no unobserved exceptions are leaked in such cases.
Recommended action
If your code catches an ObjectDisposedException from any of the Socket.End*
methods, change it to catch SocketException and refer to SocketException.SocketErrorCode to query the underlying reason.
Note
APM code should always make sure that End*
methods are invoked after the corresponding Begin*
methods, even if the socket is closed.
Affected APIs
- 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