【问题标题】:Error message handling due to exceptions异常导致的错误消息处理
【发布时间】:2012-05-01 21:00:04
【问题描述】:

我有一个代码可以在发生其他功能的事件中重新启动服务。

我对事件中的所有内容都进行了尝试,如下所示:

private void btnApply_Click(object sender, EventArgs e)
    {
        try
        {               
            applyChangesAndCheckRestartService();
        }
        catch (Exception ex)
        {
            MessageBox.Show("Error loading page.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }

private void applyChangesAndCheckRestartService()
    {
        string svrPortNo = CommonCodeClass.getTagValue(CommonCodeClass.xml_SvrPortNoTag, CommonCodeClass.configLocation + CommonCodeClass.configXML);               

        if (!ApplyChangesForSettings())
        {                
            return;
        }

        if (svrPortNo != tbSvrPortNo.Text)
        {               
            CommonCodeClass.CheckToRestartService();
        }
    }

现在,如果在 ApplyChangesForSettings() 期间出现错误,我将收到一个错误弹出窗口“错误加载页面”。

如果 CheckToRestartService() 中出现错误,由于 try catch,我将得到同样的错误。

有没有更好的方法来处理这个问题。

我不介意 ApplyChangesForSettings() 的错误加载页面,但对于 CheckToRestartService() 我希望看到类似“无法重新启动服务”的错误。

感谢任何建议。 谢谢

internal static void CheckToRestartService()
    {
        DialogResult result = MessageBox.Show(CommonCodeClass.resartServiceMessage, "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
        if (result == DialogResult.Yes)
        {
            CommonCodeClass.RestartService(CommonCodeClass.serviceName, 60000);
        }
    }

【问题讨论】:

    标签: c# winforms try-catch


    【解决方案1】:

    他们会抛出不同的异常吗?如果他们这样做,您可以使用异常过滤:

    private void btnApply_Click(object sender, EventArgs e)
    {
        try
        {               
            applyChangesAndCheckRestartService();
        }
    
        // catch service start exceptions
        catch (InvalidOperationException ioex)
        {
            // display message that couldn't start service
        }
    
        // catch rest
        catch (Exception ex)
        {
            MessageBox.Show("Error loading page.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }
    

    更新这是假设您正在调用类似 ServiceController.Start() 的东西,它在失败时抛出 InvalidOperationException,您可以轻松地自己抛出这个错误条件或创建您自己的自定义异常。

    if (/* service didn't start */)
    {
        throw new InvalidOperationException("Could not start service.");
    }
    

    【讨论】:

    • 我喜欢你的想法,但如何去 ioex 并抓住它。我已经编辑了我的答案以显示重启服务功能。请看一看。谢谢
    • @user175084 对不起,我想我在你的评论中丢失了一些东西。那是如何抛出 ioex?
    • 是的,对不起.. 喜欢如何为它创建一个单独的异常??
    • @user175084 抱歉,我假设您只是捕获了 ServiceController 本身在 Start() 失败时抛出的异常,但您可以轻松地自己抛出它。
    【解决方案2】:

    你要么需要

    • applyChangesAndCheckRestartService中捕获异常
    • 或者你可以通过ref f.e.传递一个enum。叫RestartStatus

      enum RestartStatus{success, unableToRestart, unableToApplySettings};
      
      RestartStatus status = RestartStatus.success;
      applyChangesAndCheckRestartService(status);
      if(status != RestartStatus.success) //....
      
      private void applyChangesAndCheckRestartService(out RestartStatus status)
      {
          // set the status variable accordingly
      }
      

    第三种方法是使用custom exceptions,您可以单独捕获。

    【讨论】:

      【解决方案3】:

      也许你只需要用单独的 try/catch 块包装不同的函数:

          try {
              if (!ApplyChangesForSettings())
                 return;
          }
          catch (Exception ex) {
              MessageBox.Show("Error loading page.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
          }
      
          if (svrPortNo != tbSvrPortNo.Text) {      
              try {         
                  CommonCodeClass.CheckToRestartService();
              }
              catch (Exception ex) {
                  MessageBox.Show("Unable to restart services.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
              }
          }
      

      或者,如果它们抛出不同的类型,您可以考虑捕获不同类型的异常:

      string errmsg = string.empty;
      try { 
          DoSomething();
      }
      catch (FooException) {
         errmsg = "There was a Foo error";
      }
      catch (WidgetException) {
         errmsg = "There was a problem with a Widget";
      }
      catch (Exception ex) {
         errmsg = "General problem: " + ex.Message;
      }
      
      if (!string.IsNullOrEmpty(errmsg))
         MessageBox.Show(errmsg);
      

      另见:

      【讨论】:

        【解决方案4】:

        处理这种情况的最快方法是在您的内部方法中的某个人失败并在 btnApply_Click 中捕获消息时抛出异常。

        MessageBox.Show(ex.Message, "Error",  .....);
        

        最正确的方法是创建自己的异常类型并在方法内部,如果有失败条件抛出你自己的异常。例如创建一个这样的类

        public class RestartServiceException : Exception
        {
            public RestartServiceException(string message)
                : base(message)
            {
            }
            // You could also write other constructors with different parameters and use internal logic
            // to process your error message
        }
        

        然后,当您的 CheckToRestartService 方法中出现失败条件时,使用该类的实例

           if(fail == true)
               throw new RestartServiceException("The service could not be started because .....");
        

        【讨论】:

        • 我想这样做。是否有包含上述步骤的示例或示例页面??
        • 其实并不复杂。您需要创建一个从基类 Exception 派生的类。然后您可以实现您的方法或内部变量来表示您的消息和错误条件。在这个link 你可以找到来自 MSDN 的参考资料