Вложенный try-catch и возврат ошибок

266
04 ноября 2017, 12:10

В программе обрабатывается массив записей из базы данных с помощью цикла foreach. Для каждой записи происходит формирование класса запроса и потом отправка этого запроса на сервис. При возникновении ошибки при обращении к сервису (например сервис не доступен или превышено время ожидания) нужно перейти к следующей записи, и попробовать обработать текущую запись в следующий раз. Если ошибка возникла при формировании класса запроса мне необходимо присвоить данной записи из бд статус ошибочной и закрыть ее. Решение вижу следующим образом

foreach (var item in collection)
{
    switch (code)
    {
        case 1:
            try
            {
                //формируем класс зпроса 
                try
                {
                    //отправляем запрос на сервис
                }
                catch (Exception ex)
                {
                    //возникла ошибка обращения к сервису  
                    //переходим к след итерации цикла
                    continue;
                    //throw;
                }
            }
            catch (Exception ex)
            {
                //"закрываем" данную запись 
                //throw;
            }
            break;
        //...
    }
}

Но сомневаюсь как вложенность try-catch скажется на производительности (по сути в каждом case будет данная конструкция), возможно есть более правильное решение?

Answer 1

А как на счет того, чтобы сделать это следующим образом?

Первое - поменять switch по int на более понятный Enum.

Второе - создать статический (а возможно и нет...) класс, который будет создавать запросы и отправлять их на сервер, например RequestHandler:

class RequestHandler{
    public static Request makeRequest(EnumValue){
        /**
         * Перенести switch сюда.
         * В каждом case выбрасывать кастомную ошибку "на верх" из этого метода.
         * Например, throw new MakeRequestException();
         */
    }    
    public static void sendRequest(Request request){
        /**
        * Посылаем нужный запрос.
        * Если возникает ошибка - по аналогии прокидываем ее "на верх".
        * Например, throw new SendRequestException()
        */
    }
}

Далее уже Ваш код приобретет более "понятный" вид:

foreach(var item in collection){
    try{
        var request = RequestHandler.makeRequest(item.code);
        RequestHandler.sendRequest(request);
    } catch (MakeRequestException ex) {
       //"закрываем" данную запись 
    } catch (SendRequestException ex) {
       continue;
    }
}

Еще более логичным, правильным было бы вынести метод sendRequest в класс Request

Что даст такое разбиение кода?

  1. Уменьшение кода (не нужно будет писать под каждый кейс одинаковый try/catch
  2. Более удобная читаемость кода (каждое действие разбито на логические единицы (методы и классы), switch внутри не по абстрактным единицам-ноликам, а со вполне логическими названиями.
Answer 2

Если вы работаете с внешними сервисами (как база данных в вашем случае), то это будет самим медленным местом вашего приложения. Скорость выполнения try-catch инструкций будет на порядки ниже, и вам не стоит беспокоится об этом.

Вложенность try-catch никак не влияет на производительность, самая медленная операция - это вброс исключения, и она не зависит от вложенности блоков.

Беспокоится о производительности try-catch стоит только тогда, когда вы собираетесь вбрасывать миллионы исключений в секунду.

А по вашему коду, не совсем понятно, зачем вам вложенность. Почему не сделать так:

try {
    //формируем класс зпроса
}
catch {
    //"закрываем" данную запись;
    continue;
}
try {
    //отправляем запрос на сервис
}
catch { continue; }
READ ALSO
Изменить поле в listview wpf c#

Изменить поле в listview wpf c#

Добавляю значение в listview так :

276
Классы и их наследование с#

Классы и их наследование с#

Доброго времени суток! Вопрос в следующем: Есть класс TableClassParent вот выдержка из этого класса

250
Запечатанный класс или ServiceLocator Catel?

Запечатанный класс или ServiceLocator Catel?

Думаю кто работал с данным фреймворком не нужно объяснять что такое сервисы в Catel, и для чего они используются

237
C# Unity3D - Чекпоинт

C# Unity3D - Чекпоинт

Как можно сделать невидимые чекпоинты, и когда персонаж проходит через них, у него появляются новые способности(Например: в коде, персонаж...

252