将try-catch放在循环中是不错的做法,直到try块中的所有语句都被执行而没有任何异常?

时间:2014-01-14 08:29:45

标签: c# sockets try-catch

我正在尝试开发一个多播接收器程序,并完成了套接字初始化,如下所示:

    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
         }
     }

当我的PC没有连接到网络时,SetSocketOption方法抛出异常甚至连网络后, 我无法接收数据,因为未设置套接字选项。

为了避免这种情况,我使用了一个在后台检查中运行的线程 对于网络可用性,一旦网络可用,它就会设置套接字选项。

它适用于某些PC,但在其他一些PC中,NetworkInterface.GetIsNetworkAvailable() 在网络连接之前返回true (正在确定网络)。

因此,为了确保设置Socket选项,我使用了bool变量sockOptnSet 设为的 true如果try块中的所有语句都按照方法中显示的方式执行public void SetSocketOptions() 这个程序在我试过的所有PC上运行良好,但我怀疑我可以依赖它来工作多少。

我的问题是:

1)这是一个好习惯吗?

2)如果没有,它可能导致的错误或问题是什么?我怎样才能以更好的方式实现它?

2 个答案:

答案 0 :(得分:4)

  

这是一个好习惯吗?

不,不是一个好习惯。绝大多数例外情况(包括您的第一个例外)都属于烦恼例外。软件应该工作,在测试时运行良好,但不在用户的机器上运行。出了点问题,但是你不知道什么,并且没有任何有意义的事情你能做些什么。试图保持你的程序运行是没用的,它不能完成应该做的工作。在您的情况下,没有希望套接字在没有网络时会接收数据。而且,正如您所发现的那样,尝试解决问题只会引发更多问题。这很正常。

  

如果这是不好的做法,我该如何以更好的方式实施呢?

你需要人类的帮助。用户将不得不设置机器以提供有效的网络连接。这需要一个用户界面,你必须有办法告诉人类他需要做些什么来解决你的问题。你可以根据自己的意愿将其变得复杂或简单。只是一条错误消息,Exception.Message的逐字副本就足够了。为AppDomain.CurrentDomain.UnhandledException事件编写事件处理程序是一个非常好(和必需)的策略。 Microsoft花费了大量精力使异常消息尽可能清晰且有用,甚至以用户的母语为您本地化,您希望利用它。即使异常消息令人费解,对消息文本的快速Google查询也会返回数百次点击。有了这个事件处理程序,您就不必执行任何特殊操作。您的程序会自动终止,并且您的用户知道如何处理它。

你当然可以使它更复杂,你发现SetSocketOption()在网络可用后很可能会失败,但是当你等待足够长时间时就会​​工作。所以这实际上是一个错误的条件,你可以解决,只需等待足够长的时间。是否应该编写代码来处理这个问题是你必须自己决定的。当你对程序的行为方式有足够的经验时,这是你写的东西,你从来没有预先写过。通常是来自您的计划用户的反馈。

答案 1 :(得分:3)

评论中的一些好建议,让我们“扩展它。”

首先,我将所有这些套接字代码放在其自己的类中,在表单之外。这使它成为'自己的实体,在语义上更容易理解。此类可以具有属性Initialised,该属性最初设置为false。您在表单中执行的第一件事是在此类上调用Initialise方法,该方法尝试设置套接字选项并在网络不可用时捕获相关的异常。如果 可用,我们会将Initialised属性设置为true

如果不可用,我们设置一个超时(参见System.Threading.Timer),在'x'秒后调用此相同的函数(可能带有重试计数)。我们再一次发现自己回到了这个Initialise函数中,可能还有一个开头提到的重试计数。再一次,如果它可用,我们很好 - 如果没有,再次设置计时器。最后,在'x'重试后如果我们没有初始化,我们可以抛出异常或设置一些其他失败属性来表明我们无法继续。

您的Form类可以定期检查(或挂钩事件)以确定套接字现在是否已准备好进行通信。如果失败你可以优雅地退出,或者因为我们的课程很好并且抽象,试图再次启动整个过程。