【问题标题】:modifying existing program to handle exceptions better修改现有程序以更好地处理异常
【发布时间】:2012-09-13 01:59:57
【问题描述】:

我正在开发一个现有的 C# 程序,该程序在程序和运行该程序的计算机之外查询和更改各种资源。该程序适用于大多数计算机,但偶尔会在随机计算机上随机失败。发生这种情况时,除了用户告诉我们有关屏幕上抛出的异常(他们可能已经清除也可能尚未清除)之外,我们没有其他反馈。即使他们为我们将其留在屏幕上,它也几乎没有为我们提供有用的信息。从那以后,我修改了程序以记录特定事件并将信息收集到一个文本文件中,我可以使用该文件来估计程序停止的位置。这至少是一个开始,但是通过阅读 stackoverflow.com 以及其他论坛上的许多线程,我知道该程序至少需要尝试处理在查询和修改 LDAP、DS、DNS 时可能出现的特定异常,SQL等。

目前,所有待办事项代码周围只有一个大的 try 块,每个块的末尾只有一个 catch 块。

private void method_name()
{
    try
    {
       //many lines of to do code calling many other methods
    }
    catch (exception ex)
    {
        MessageBox.Show("An Error has occurred in method_name() :" + ex.Message);
    }

我的第一个想法是在较大的 try 块中嵌套更具体的 try/catch 块,但我一直遇到变量在不同上下文中无法访问的问题。例如

try
{
   LdapConnection ldapConn = new LdapConnection();
   ldapConn.Connect(details of connection);
   ldapConn.Bind(details of bind statement);
   LdapSearchQueue queue = ldapConn.Search(search criteria and such);
   LdapMessage message;
}
catch (somesortofexception ex)
{
   //do something sensible about it
}

while ((message = queue.getResponse()) != null)
{
   //do things with message
}
ldapConn.Disconnect();

问题是消息和队列在 try 块之外无法访问。这只是我正在尝试使用的“//many lines of to do code calls many other methods”的一个例子。

所以这是我的问题:

在上面的示例中尝试使 try 块更大以包括 while 循环和 ldap 断开连接,或者只是离开大的 try 循环,列出在此期间发生的事情并创建许多 catch 块会更好吗?最后捕获特定的异常?根据我在本网站上阅读的内容,我觉得在特定代码周围放置较小的 try 块是可行的方法。

我是否应该像我一直在尝试实现的那样使用较小的 try 块,只使用一个 catch 块来捕获在该小 sn-p 代码中引发的任何异常并将其记录到我的日志文件中,或者我应该尝试捕获特定的异常吗?除了将它们记录到文件中之外,我真的没有什么不同的方法可以处理这些异常。

我需要抛出异常吗?除了用简单的英语消息说出现问题并联系 IT 之外,我真的不希望有任何东西冒泡给用户。目前没有一个 catch 块抛出任何东西。

【问题讨论】:

  • 这是什么类型的应用程序?窗体?控制台?

标签: c# exception try-catch


【解决方案1】:

关于分解异常,我总是将连接代码与查询代码分开。

所以这会变成:

LdapConnection ldapConn = new LdapConnection();
try
{
   ldapConn.Connect(details of connection);
   ldapConn.Bind(details of bind statement);
}
catch (somesortofexception ex)
{
   //Log, send error message..
   ldapConn = null;
}

if (ldapConn != null)
{
    try
    {
         //Do what you need with your connection
    }
    catch (Exception ex)
    {
         //Log, Error....
    }
    finally
    {
        //Disconnect your ldap here
    }
}

理想情况下,我也会将所有连接代码和搜索代码放在单独的方法中, 所以你会有一些更好的堆栈跟踪。

关于错误消息,我也会使用一些通用消息并将异常细节记录到某种文件中(http://logging.apache.org/log4net/),这对于拥有格式良好的日志文件非常有用。

【讨论】:

  • 如果bind语句出了问题,ldapConn.Disconnect()也会抛出异常吗?
  • 据我所知,如果绑定出现问题,您应该仍然处于连接状态,因此断开连接应该可以安全调用。您可以通过在调用 bind 时提供无效凭据来轻松尝试。
  • 到目前为止,这非常有帮助。还有几件事:
  • 到目前为止,这非常有帮助。还有几件事:如果我设置 ldapConn = null;在 try 块之前的开头,它会收到异常“对象引用未设置为对象的实例”。我可以通过仅将构造函数放在 try 之前而不将其设置为 null 来避免这种情况。我不知道这是否是不好的做法,但它有效.....另一件事是我想确保运行 ldapConn.Disconnect() 但我希望我的 catch 循环记录错误并停止程序这将阻止 finally 块运行。我应该在 catch 块中放另一个 ldapconn.Disconnect 吗?
  • 好的,所以我只是重新阅读了您的代码并注意到您没有 ldapConn = null;无论如何,在第一个尝试语句之前。我不知道我从哪里得到的。
【解决方案2】:

只要您期望该异常并且可以在本地处理它,就可以使用吞下特定异常的本地 catch 块。在这种情况下,您可以仅根据异常包含的内容向用户提供信息,或者如果您想在日志记录和/或消息中包含变量定义,则可以将变量定义移到 try 块上方。

对于您没有预料到的异常,您应该让它们向上冒泡到调用堆栈的顶部,在那里它们可以由全局处理程序记录下来,然后才能优雅地退出程序。您不希望通过吞下这些异常来潜在地将尸体钉在直立位置。

假设这是一个 WinForms 应用程序,全局处理程序的设置如下所示:

public static void Main(string[] args)
{
    // Switch-off the Windows Forms default handler for unhandled exceptions.
    // NB From .NET 4 upwards, this won't work if the process state is corrupted.
    Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

    // Setup event handler to intercept an unhandled exception on a UI thread.
    // NB The exception will still terminate the application. 
    // But you can show a MessageBox and/or log the exception. 
    Application.ThreadException += 
        new ThreadExceptionEventHandler(App_UiThreadException);

    // Setup event handler to intercept unhandled exception on a non-UI thread.
    AppDomain.CurrentDomain.UnhandledException += new 
        UnhandledExceptionEventHandler(App_NonUiThreadException);

    // Run the application (open main form etc).    
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-06
    • 2011-11-29
    • 2013-10-07
    相关资源
    最近更新 更多