4

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

目前,所有待办事项代码周围只有一个大的 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 块,可以只使用一个 catch 块来捕获该小段代码中引发的任何异常并将其记录到我的日志文件中,或者我应该尝试并捕获具体例外?除了将它们记录到文件中之外,我真的没有什么不同的方法可以处理这些异常。

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

4

2 回答 2

0

只要您期望该异常并且可以在本地处理它,那么吞下特定异常的本地 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).    
}
于 2012-09-20T17:02:21.337 回答
0

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

所以这会变成:

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/)中,这对于拥有格式良好的日志文件非常好。

于 2012-09-20T17:05:11.110 回答