简体   繁体   中英

Is it good practice to put try-catch in a loop until all statements in the try block is executed without any exceptions?

I was trying to develop a multicast receiver program and socket initialization was done as shown below:

    public void initializeThread()
    {
        statuscheckthread = new Thread(SetSocketOptions);
        statuscheckthread.IsBackground = true;
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        rxsock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
        iep = new IPEndPoint(IPAddress.Any, 9191);
        rxsock.Bind(iep);
        ep = (EndPoint)iep;

        initializeThread();
        statuscheckthread.Start();
    }

    public void SetSocketOptions()
    {
         initializeThread(); //re-initializes thread thus making it not alive
         while (true)
         {
             if (NetworkInterface.GetIsNetworkAvailable())
             {
                 bool sockOptnSet = false;
                 while (!sockOptnSet)
                 {
                     try
                     {
                         rxsock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Parse("224.50.50.50")));
                         rxsock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 64);
                         sockOptnSet = true;
                     }
                     catch
                     {
                         //Catch exception here
                     }
                 }
             }
             break; // Break out from loop once socket options are set
         }
     }

When my PC is not connected to a network, SetSocketOption method was throwing exception and even after network is connected, I was unable to receive data because socket options are not set.

To avoid this I used a thread which runs in the background checking for network availability and once network is available, it sets the socket options.

It works properly in some PC's but in some others, NetworkInterface.GetIsNetworkAvailable() returned true before network got connected (while network was being identified) .

So, to make sure Socket options are set, I used a bool variable sockOptnSet which is set as true if all the statements in the try block is executed as shown inside the method public void SetSocketOptions() This program works fine in all PC's I tried, but I am doubtful about how much I can rely on this to work.

My questions are:

1) Is this good practice?

2) If not, what are the possible errors or problems it may cause? And how can I implement it in a better way?

Is this a good practice?

No, not a good practice. The vast majority of exceptions, including your first one, fall in the category of vexing exceptions. Software is supposed to work, worked well when you tested it, but doesn't on the user's machine. Something went wrong but you do not know what and there isn't anything meaningful that you can do about it. Trying to keep your program going is not useful, it cannot do the job it is supposed to do. In your case, there's no hope that the socket is ever going to receive data when there is no network. And, as you found out, trying to work around the problem just begets more problems. That's normal.

If this is bad practice, how can I implement it in a better way?

You need help from a human. The user is going to have to setup the machine to provide a working network connection. This requires a user interface, you must have a way to tell a human what he needs to do to solve your problem. You can make that as intricate or as simple as you desire. Just an error message, a verbatim copy of the Exception.Message can be enough. Writing an event handler for the AppDomain.CurrentDomain.UnhandledException event is a very good (and required) strategy. Microsoft spent an enormous amount of effort to make exception messages as clear and helpful as possible, even localizing them for you in the user's native language, you want to take advantage of that. Even if the exception message is mystifying, a quick Google query on the message text returns hundreds of hits. With this event handler in place, you don't have to do anything special. Your program automatically terminates and your user knows what to do about it.

You can certainly make it more intricate, you discovered that SetSocketOption() is liable to fail right after the network becomes available but works when you wait long enough. So this is actually an error condition that you can work around, just by waiting long enough. Whether you should write the code to handle this is something that you have to decide for yourself. It is something you write when you have enough experience with the way your program behaves, you never write it up front. Usually as a result from feedback from the users of your program.

Some good advice in the comments, lets' expand on it.

Firstly, I would put all this socket code in to its' own class, outside of the form. This makes it its' own entity and semantically easier to understand. This class could have a property Initialised , which is initially set to false . The first thing you do in your form is call an Initialise method on this class which attempts to set socket options and catches the relevant exceptions if the network is not available. If it is available, we set our Initialised property to true .

If not available, we set a single timeout (see System.Threading.Timer ) that calls this same function (potentially with a retry count) after 'x' seconds. Once again we'll find ourselves back in this Initialise function, perhaps with a retry count mentioned at the beginning. Once again, if it is available, we're good - if not, set the timer again. Eventually, after 'x' retries if we're not initialised we can throw an exception or set some other failure property to indicate that we can't proceed.

Your Form class can periodically check (or hook in to an event) to determine whether the socket is now ready for communication. In case of failure you can gracefully quit out, or because our class is nice and abstracted, attempt to start the whole process again.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM