Безостановочные исключения в C # - PullRequest
5 голосов
/ 16 марта 2009

Я пишу код C # 2.0, который должен выполнять базовые HTTP GET и POST. Я использую System.Net.HttpWebRequest для отправки обоих типов запросов и System.Net.HttpWebResponse для получения обоих. Мой код для GET выглядит так:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(String.Format("{0}?{1}",
    URLToHit,
    queryString));
request.Method = "GET";
request.Timeout = 1000; // set 1 sec. timeout
request.ProtocolVersion = HttpVersion.Version11; // use HTTP 1.1
try
{
    HttpWebResponse response = (HttpWebResponse)request.GetResponse();
}
catch(WebException e)
{
    // If I do anything except swallow the exception here, 
    // I end up in some sort of endless loop in which the same WebException 
    // keeps being re-thrown by the GetResponse method. The exception is always 
    // right (ie: in cases when I'm not connected to a network, it gives a 
    // timed out error, etc...), but it should not be re-thrown!
}

И мой POST-код очень похож.

Последняя строка работает нормально, когда URLToHit возвращает HTTP-статус 200, но при любых других обстоятельствах (т. Е. HTTP-статус не 200, нет подключения к сети и т. Д.) Возникает исключение System.Net.WebException (которое ожидается, в соответствии с документами MSDN). Тем не менее, мой код никогда не продвигается дальше этой линии.

Когда я пытаюсь отладить это, я обнаруживаю, что не могу перешагнуть или продолжить после этой последней строки. Когда я пытаюсь это сделать, запрос повторно выдается, а исключение перебрасывается.

Любые идеи о том, что я могу сделать, чтобы сделать запрос только один раз? Я никогда не видел ничего подобного в коде, основанном на исключениях, и у меня нет идей. Ничего подобного не происходит ни в каких других частях моего кода, только в частях, которые касаются функциональности и конструкций System.Net.

Спасибо!

(Обновление: добавлен метод try / catch для метода GetRequest)

Ответы [ 5 ]

1 голос
/ 16 декабря 2010

С другой стороны, есть разница между этими двумя фрагментами кода:

catch (Exception e)
{
    throw e;
}

catch (Exception e)
{
    throw;
}

Первый пример фактически сбрасывает трассировку стека в исключении в текущее местоположение стека, второй пример сохраняет существующую трассировку стека. Это может помочь вам отладить вашу проблему, если вы переключите свой код на второй пример.

1 голос
/ 15 декабря 2010

У меня точно такая же проблема. Вот как я это делаю:

        bool shouldRetry = true;
        do {
            try
            {
                Stream newStream = myHttpWebRequest.GetRequestStream();
                newStream.Write(byteArray, 0, byteArray.Length);
                newStream.Close();
                HttpWebResponse response = (HttpWebResponse)myHttpWebRequest.GetResponse();
                shouldRetry = false;
                response.Close();
                tries++;
                status = response.StatusDescription;
            }
            catch (WebException e)
            {
                tries++;
                if (tries >= 5)
                {
                    throw e;
                }
                else
                {
                    Thread.Sleep(1000);
                }
            }
        } while (shouldRetry);

Чтобы вызвать исключение, я изменил свою таблицу хостов, чтобы URI перешел к моему локальному хосту, который не дает правильного ответа.

Но исключение постоянно выбрасывается! Если я отлаживаю в Visual Studio, он останавливается на

throw e;

с уведомлением / коробкой "неучтенное исключение". если я нажимаю «play», чтобы продолжить отладку, то же исключение выдает строка, я не могу идти вперед в коде.

Кроме того, не имеет значения, ГДЕ я выдаю ошибку. Я попытался сохранить и выбросить его после do / while, после вызова функции и т. Д. Исключение все еще выбрасывается и постоянно присутствует. Единственный выход - остановить отладчик / выйти из веб-сервера. (на локальном хосте процесс занимает 100% своего ЦП), когда это состояние возникает на хосте веб-сервера, IIS через некоторое время перезапускается.

Аарон, ты когда-нибудь решал эту проблему? Мне нужно это исключение, и я не могу его "проглотить".

ОБНОВЛЕНИЕ: 2010-12-16

Этот код находится в функции с именем send (). Эта функция на самом деле вызывается в ThreadPool.QueueUserWorkItem следующим образом.

            ThreadPool.QueueUserWorkItem((object state) =>
            {
                Thread.Sleep(1);
                try
                {
                    send();
                }
                catch (Exception e)
                {
                    throw e;
                }
            });

В настоящее время я пытаюсь выяснить, связано ли это с безостановочными исключениями, которые в конечном итоге приводят к сбою сервера в моем случае. Как я уже сказал .. Неважно, ГДЕ я ловлю исключение.

ОБНОВЛЕНИЕ: 2010-12-16 (часть 2)

Я НЕ получаю нескончаемую ошибку, если я избегаю использования ThreadPool.QueueUserWorkItem.

Я продолжу исследовать .. Но, возможно, я мог бы обойтись без ThreadPool.QueueUserWorkItem.

ОБНОВЛЕНИЕ: 2010-12-16 (часть 3)

Thread.CurrentThread.Abort();

Вместо броска ошибка решает мою проблему

1 голос
/ 16 декабря 2010

Я видел подобные проблемы с этим, и обычно только в самом отладчике строка, генерирующая исключение, перезапускается, но это происходит только тогда, когда исключение в конечном счете не обработано.

Вы говорите, что это поведение проявляется только при повторном броске в блоке catch. Поскольку вы перебрасываете исключение, где это исключение в конечном итоге будет поймано и обработано (то есть обработчиком перехвата, который не заканчивается на (пере) бросок)?

Если ответ «никуда», то это ваша проблема - в отладчике вы, вероятно, увидите повторное выполнение строки, генерирующей исключение, и при нормальном запуске приложение будет аварийно завершать работу из-за отсутствия исключение.

1 голос
/ 16 марта 2009

В C # нет такого понятия, как "безостановочное" исключение. Чтобы контролировать, что происходит во время исключения, вы используете блок try-catch.

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(String.Format("{0}?{1}",
    URLToHit,
    queryString));
request.Method = "GET";
request.Timeout = 1000; // set 1 sec. timeout
request.ProtocolVersion = HttpVersion.Version11; // use HTTP 1.1

try
{
    HttpWebResponse response = (HttpWebResponse)request.GetResponse();

    // Code here runs if GetResponse() was successful.
}
catch (WebException ex)
{
    // Code here runs if GetResponse() failed.
}

// Code here is always run unless another exception is thrown. 

Причина, по которой нет «безостановочных исключений», заключается в том, что, если есть исключение, ваш код не может делать то, что вы хотели. Например, что вы ожидаете от переменной «response»? Что бы вы сделали с этим? Блок try-catch дает вам полный контроль над этим.

0 голосов
/ 16 декабря 2010

Вот немного пищи для размышлений: отладчик также может выполнять код. Например, когда вы оцениваете свойство (в часах, или в QuickWatch, или даже просто наводите указатель мыши на его имя для всплывающей подсказки значения), отладчик выполняет основной код. И ударить любые точки останова, которые он встречает во время этого. Возможно, это причина? Что такое стеки вызовов в последующих исключениях? Это также происходит без отладчика?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...