I am receiving data from UdpClient via the usual async callback:
private void OnUdpData(IAsyncResult result)
{
byte[] data = _udpReceive.EndReceive(result, ref _receiveEndPoint);
//Snip doing stuff with data
_udpReceive.BeginReceive(OnUdpData, null);
}
When I Close()
the UdpClient in the main thread, the callback fires as I would expect, but at this point _udpReceive
is already disposed and I get an ObjectDisposedException
when I try and call EndReceive()
. I was expecting to just get an empty buffer.
What is the correct way to handle this? Is there some member of UdpClient
I can check before trying to use it, or it the only way to wrap it all in a try{}
and catch the ObjectDisposedException
? That seems pretty nasty for a normal close.
You can do this to check if its disposed. Client is set to null when the UdpClient is disposed.
private void OnUdpData(IAsyncResult result)
{
if (_udpReceive.Client == null)
return;
byte[] data = _udpReceive.EndReceive(result, ref _receiveEndPoint);
//Snip doing stuff with data
if (_udpReceive.Client == null)
return;
_udpReceive.BeginReceive(OnUdpData, null);
}
Although because you are closing it in a separate thread you may end up with a race condition. It would be best to just catch ObjectDisposedException and SocketException.
private void OnUdpData(IAsyncResult result)
{
try
{
byte[] data = _udpReceive.EndReceive(result, ref _receiveEndPoint);
//Snip doing stuff with data
_udpReceive.BeginReceive(OnUdpData, null);
}
catch (Exception e)
{
//You may also get a SocketException if you close it in a separate thread.
if (e is ObjectDisposedException || e is SocketException)
{
//Log it as a trace here
return;
}
//Wasn't an exception we were looking for so rethrow it.
throw;
}
}
This is entirely by design. You did something exceptional, you closed the socket even though you expected data to be received. So you'll get an exception. The .NET framework always makes sure that asynchronous calls are completed and that the abort reason is signaled in the callback when you call EndXxx(). Good idea, that lets you clean up any state associated with the callback.
You can make it non-exceptional by waiting until the transfer is complete, stop calling BeginReceive() and then close the socket. But that isn't always practical or sometimes you really want to terminate early. Not a problem, simply catch the ObjectDisposedException and get out. Of course, do consider what happens to the app on the other end of the wire. Anything it sends afterward is going to fall in the bit-bucket with no way for it to find out.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With