在async/await中正确处理HttpClient异常

32

我希望有人能为我解决一个涉及HttpClient异步/等待异常处理的问题。我写了一些代码来说明,并在Windows Phone 8设备和模拟器上执行:

    private async void SearchButton_Click(object sender, EventArgs e)
    {
        try
        {
            HttpClient client = new HttpClient();
            System.Diagnostics.Debug.WriteLine("BEGIN FAULTY REQUEST:");
            string response = await client.GetStringAsync("http://www.ajshdgasjhdgajdhgasjhdgasjdhgasjdhgas.tk/");
            System.Diagnostics.Debug.WriteLine("SUCCESS:");
            System.Diagnostics.Debug.WriteLine(response);
        }
        catch (Exception exception)
        {
            System.Diagnostics.Debug.WriteLine("CAUGHT EXCEPTION:");
            System.Diagnostics.Debug.WriteLine(exception);
        }
    }

点击调用此函数的按钮,将在调试器控制台中生成以下输出,最有趣的部分是粗体字体:

BEGIN FAULTY REQUEST:

类型为“System.Net.WebException”的异常在“System.Windows.ni.dll”中发生,并且在托管/本机边界之前未处理

类型为“System.Net.WebException”的异常在“System.Windows.ni.dll”中发生,并且在托管/本机边界之前未处理

类型为“System.Net.Http.HttpRequestException”的第一次机会异常在“mscorlib.ni.dll”中发生

类型为“System.Net.Http.HttpRequestException”的异常在“mscorlib.ni.dll”中发生,并且在托管/本机边界之前未处理

CAUGHT EXCEPTION:

(这里打印出HttpRequestException)

当然,在这种情况下,我预计会出现错误,因为我正在调用无意义的URL。我不理解的是,为什么调试器报告异常未处理,而输出同时报告异常已被捕获。此外,在输出被打印时,应用程序的UI端变得不那么响应,这表明可能有问题。

在使用异步和等待时,这不是处理异常的方法吗?感谢任何帮助!谢谢。


2
就响应性而言,您不应在UI事件中运行长时间进程。这些应该是快速的,长时间运行的进程应该在另一个线程中完成。请尝试使用BackgroundWorker http://msdn.microsoft.com/en-us/library/System.ComponentModel.BackgroundWorker.aspx - Harrison
3个回答

55

由于您正在使用 HttpClient,请尝试使用response.EnsureSuccessStatusCode();

现在,当响应状态不是成功代码时,HttpClient将抛出异常。

try
{
    HttpResponseMessage response = await client.GetAsync("http://www.ajshdgasjhdgajdhgasjhdgasjdhgasjdhgas.tk/");
    response.EnsureSuccessStatusCode();    // Throw if not a success code.

    // ...
}
catch (HttpRequestException e)
{
    // Handle exception.
}

代码的原始来源: http://www.asp.net/web-api/overview/advanced/calling-a-web-api-from-a-net-client


4
如果您希望response的类型为HttpResponseMessage,那么您必须使用client.GetAsync而不是client.GetStringAsync - kaolick
我一直在尝试将错误请求(400)捕获为异常。在我的情况下,我的应用程序没有命中Web服务器的有效端点(可能是因为服务器没有更改它)。我已经苦思冥想了半个小时,搜索为什么这不会作为异常捕获。你的答案真的帮了我很多。这是处理这种情况的正确方式吗?将错误请求捕获为异常?谢谢。 - Chucky

12

这是调试器的一个特性。它确定异常是“未捕获”的,因为它目前还没有被捕获。在这种情况下,这是预期的行为。

您正在正确处理异常。


2
我会说它被标记为“未捕获(uncaught)”,因为它没有被用户代码捕获,而是被TPL捕获。 - usr
异常没有被处理,而是被隐藏了(即使它被记录到 Debug.WriteLine 中,在发布模式下不会显示)。在发布时构建,如果 HTTP 调用失败,您将不知道失败的原因(甚至不知道它失败了)。 - Stuart
@Stuart:对于问题中发布的代码,异常将被捕获。 - Stephen Cleary

1
调试器告诉你这个异常是第一次出现。当调试器连接到进程时,它会收到每个抛出的异常的通知,然后根据调试器的配置决定如何处理它。你可以查看什么是第一次机会异常?以获取更多详细信息。
另外,请仅捕获特定的异常,以便了解你期望发生哪些异常以及为什么。

谢谢,我会仔细阅读!我同意你的附注,我的实际情况是不同的,我只是写这个来说明我的问题。 - Nils Holtar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接