2

I'm using an async callback in a windows service to receive UDP data broadcast on a network.

The callback uses the UDPClient.EndReceive() method to end the pending async receive. During the service OnStop() method I UDPClient.Close() the UDP client. Following this, I frequently get an ObjectDisposedException at the next call to EndReceive() in the async callback, which is being accessed on another thread.

Obviously it's no problem for me to catch this exception in the receive callback with a try { UDPClient.EndReceive(...); } but I would like to have some confidence that the caught ODE was thrown while shutting down the service (as expected) and not for some other reason. I could create a boolean flag that is set and indicates when the service is stopping, and check this in the catch block, however I feel like I am overlooking a more elegant solution.

How can I ensure that the ODE I am catching is the expected one, and not a genuinely unexpected exception?

khargoosh
  • 1,450
  • 15
  • 40
  • 1
    Just catch ODE and do not add any whistles, they just add threading bugs to your code. The MSDN documentation doesn't often describe all possible exceptions but it is quite unambiguous what ODE means in the Socket.EndReceive() article. The socket is a dead soldier, catch ODE and get out quickly. – Hans Passant Jul 22 '15 at 08:48
  • Thanks Hans for your input. The article is unambiguous in what an ODE means for the socket, true, but it hardly seems unambiguous as to the reason the socket has closed? I understand that your recommendation is probably the way to go in production, however in testing I would still like a way to ensure that the ODE was due to the socket closing as a result of **my** intended disposal of the UDP client, and not due to some other error or bug or fault. Is it really unnecessary? – khargoosh Jul 23 '15 at 22:27
  • Having to catch ODE is a sign of not using a good protocol. The other machine did not say goodbye like it should. But it is common, often because there is no such protocol. Or because a human is involved, he wants to stop the program even if it isn't done. UDP is already a lost cause. – Hans Passant Jul 23 '15 at 23:21
  • Indeed catching the ODE is basically a requirement when disposing the UDP client when an async receive has started, since the [msdn recommendation](https://msdn.microsoft.com/en-us/library/w7wtt64b%28v=vs.110%29.aspx) for cancelling the pending receive is to call the `Close()` method! I'm only using UDP to find other service instances on the network via interval broadcasts, not for communication with those nodes. But back to the question - do you happen to have any thoughts on how I can check for this, even if just in testing? Perhaps a simple bool flag is the best way to go after all. – khargoosh Jul 23 '15 at 23:55

1 Answers1

2

I ended up using a bool flag to indicate that the service was stopping. The serviceStopping flag is set to true in the OnStop() method of the service, and checked when the ObjectDisposedException is caught:

try 
{
    datagram = client.EndReceive(arClient, ref remoteEP); 
}
catch (ObjectDisposedException)
{
    //if the service is stopping this is expected
    if(serviceStopping)
    {
        //return without further processing
        //in the receiveCallback
        return;
    }

    //otherwise rethrow the exception
    throw;
}
khargoosh
  • 1,450
  • 15
  • 40