C#中的不间断异常

时间:2009-03-16 05:44:30

标签: c# .net-2.0 system.net

我正在编写一些必须执行基本HTTP GET和POST的C#2.0代码。我正在使用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时,最后一行正常工作,但在任何其他情况下(即:非200 HTTP状态,没有网络连接等...),抛出System.Net.WebException(这是预计,根据MSDN文档)。但是,我的代码永远不会超越该行。

当我尝试调试时,我发现我无法跳过或继续经过最后一行。当我尝试这样做时,重新发出请求并重新抛出异常。

关于我可以做什么来提出请求的任何想法只发出一次?我从来没有在任何基于异常的代码中看到过这样的事情,而且我没有想法。在我的代码的任何其他部分,只有处理System.Net功能和构造的部分,都不会发生这种情况。

谢谢!

(更新:在GetRequest方法周围添加了try / catch)

5 个答案:

答案 0 :(得分:1)

在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. 

没有“不间断例外”的原因是,如果存在例外,您的代码可能无法按照您的意图行事。例如,您期望“响应”变量包含什么?你会怎么做? try-catch块使您可以完全控制它。

答案 1 :(得分:1)

我有完全相同的问题。以下是我制作它的方法:

        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转到我的localhost,它没有提供任何正确的响应。

但不断抛出异常!如果我在Visual Studio中调试,它将停在

throw e;

带有“未捕获的例外”通知/框。如果我按“播放”继续调试,同一行抛出异常,我无法在代码中前进。

此外,我抛出错误并不重要。我已经尝试保存它并在do / while之后,在函数调用之后抛出它等等。异常仍然被抛出并且一直存在。离开的唯一方法是停止调试器/退出web服务器。 (在localhost上,进程占用其CPU的100%),当在Web服务器主机上发生此状态时,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,我会 NOT 得到永无止境的错误。

我会继续调查..但也许我可以在没有ThreadPool.QueueUserWorkItem的情况下进行管理。

更新时间:2010-12-16(第3部分)

Thread.CurrentThread.Abort();

而不是抛出错误解决了我的问题

答案 2 :(得分:1)

我已经看到了类似的问题,并且通常仅在调试器本身中重新运行引发异常的行,但这只有在异常最终未被捕获时才会发生。

你说它只会在你重新抛出catch块时表现出这种行为。既然你正在重新抛出异常,那么异常最终会被捕获并处理掉(即由以(重新)抛出结束的捕获处理程序)?

如果答案是“无处”,那么这就是你的问题 - 在调试器下你可能会看到重新运行异常抛出的行,并且当正常运行时,应用程序通常会因为未被捕获而崩溃异常。

答案 3 :(得分:1)

另一方面,这两个代码片段之间存在差异:

catch (Exception e)
{
    throw e;
}

catch (Exception e)
{
    throw;
}

第一个示例实际上会将异常中的堆栈跟踪重置为当前堆栈位置,第二个示例将保留现有堆栈跟踪。如果将代码切换到第二个示例,它可能会帮助您调试问题。

答案 4 :(得分:0)

这里有一些值得思考的东西:调试器也可以执行代码。例如,当您评估属性时(在监视或QuickWatch中,或者甚至只是将鼠标悬停在其名称上用于值工具提示),调试器将执行底层代码。并点击它在此期间遇到的任何断点。也许这就是原因?后续例外中的callstacks是什么?没有调试器也会发生这种情况吗?