Вопрос: изменение существующей программы для лучшего управления исключениями


Я работаю над существующей программой на 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 / catch в более крупные блоки try, но я продолжаю сталкиваться с проблемами, когда переменные становятся недоступными в разных контекстах. например

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. Это всего лишь один пример того, что было сделано с помощью «// многих строк кода, вызывающего многие другие методы», с которыми я пытаюсь работать.

Итак, вот мои вопросы:

Было бы лучше попытаться сделать блок try больше в приведенном выше примере, чтобы включить цикл while и ldap disconnect или просто оставить большой цикл try, составить список вещей, которые происходят во время этого, и создать множество блоков catch в конце уловить определенные исключения? Я чувствую, что включение меньших блоков try вокруг определенного кода - это путь, основанный на том, что я читал на этом сайте.

Должен ли я использовать меньшие блоки try, как я пытался реализовать, было бы хорошо использовать блок catch, который ловит любое исключение, поднятое внутри этого небольшого фрагмента кода и записывая его в файл журнала, или я должен попытаться поймать конкретные исключения? У меня нет ничего другого, что я могу сделать с этими исключениями, кроме как в любом случае записывать их в файл.

Нужно ли исключать исключения? Я действительно не хочу, чтобы что-то щелкало к пользователю, кроме сообщения на простом английском языке, в котором говорилось, что что-то пошло не так и связаться с ИТ. В настоящее время ни один из блоков catch ничего не бросает.


4


источник


Ответы:


Из-за исключения исключений я всегда буду отделять код подключения от запроса.

Таким образом, это станет следующим:

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/  ) неплохо для хорошо отформатированных файлов журналов.


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

0