How to find out if UdpClient has been closed / deleted?

I get data from UdpClient through a regular 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() UdpClient in the main thread, the callback fires as expected, but at the moment _udpReceive already set, and I get an ObjectDisposedException when I try to call EndReceive() . I expected to get an empty buffer.

What is the right way to handle this? Is there any UdpClient member that I can check before trying to use it, or is it the only way to wrap it all in try{} and catch an ObjectDisposedException ? This seems rather unpleasant for a normal close.

+4
source share
2 answers

It is completely by design. You did something exceptional, you closed the socket, even if you expected to receive data. Thus, you will get an exception. The .NET framework always ensures that asynchronous calls are completed and the reason for the failure is indicated in the callback when EndXxx () is called. Good idea to clear any state associated with a callback.

You can make this non-exclusive by waiting for the transfer to complete, stop calling BeginReceive (), and then close the socket. But this is not always practical or sometimes you really want to end early. Not a problem, just catch an ObjectDisposedException and exit. Of course, think about what happens with the application on the other end of the wire. Everything that he sends after this will fall into a bit bucket so that he does not recognize.

+4
source

You can do this to check if it is selected. The client is set to null when the UdpClient is deleted.

 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, since you close it in a separate thread, you may encounter a race condition. It is best to just catch an ObjectDisposedException and a 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; } } 
+5
source

Source: https://habr.com/ru/post/1396822/


All Articles