[英]HttpClient not throwing exception when using await on GetAsync
I'm using the following code to get an endpoint and write it to a cache:我正在使用以下代码获取端点并将其写入缓存:
public async Task UpdateCacheFromHttp(string Uri)
{
if (string.IsNullOrEmpty(Uri))
return;
var httpClient = new HttpClient();
var response = await httpClient.GetAsync(Uri);
if ((response != null) && (response.IsSuccessStatusCode))
{
var responseStream = await response.Content.ReadAsStreamAsync();
WriteToCache(responseStream);
}
}
The code is running on IIS.代码在 IIS 上运行。
If the endpoint can't be reached I'd expect GetAsync to throw an exception.如果无法到达端点,我希望 GetAsync 抛出异常。 Even with a Try-Catch, it never seems to fail.
即使使用 Try-Catch,它似乎也永远不会失败。 GetAsync never returns (I tried a 5 second timeout on the HttpClient, still didn't return).
GetAsync 永远不会返回(我在 HttpClient 上尝试了 5 秒超时,但仍然没有返回)。
This does throw an exception:这确实会引发异常:
public Task UpdateCacheFromHttp(string Uri)
{
var updateCacheTask = Task.Factory.StartNew(new Action(() =>
{
if (string.IsNullOrEmpty(Uri))
return;
var httpClient = new HttpClient();
var response = httpClient.GetAsync(Uri).Result;
if (response.IsSuccessStatusCode)
{
var responseStream = response.Content.ReadAsStreamAsync().Result;
WriteToCache(responseStream);
}
}));
return updateCacheTask;
}
I get the expected "Unable to connect to the remote server".我得到预期的“无法连接到远程服务器”。
I suspect it has something to do with the code running in IIS, but why?我怀疑它与在 IIS 中运行的代码有关,但为什么呢? How do I get it to properly throw the exception without the need to start a new task?
如何在不需要开始新任务的情况下正确抛出异常?
My intuition tells me that you're calling Wait
or Result
further up your call stack.我的直觉告诉我,你正在调用
Wait
或Result
进一步调用你的调用堆栈。
If that is correct, then you're causing a deadlock, as I explain on my blog .如果这是正确的,那么您将导致僵局,正如我在我的博客中所解释的那样。
As I encountered the same behaviour with no Exception being thrown, I created a sample to demonstrate the problem with a possible solution:由于我遇到了没有抛出异常的相同行为,我创建了一个示例来演示该问题的可能解决方案:
using System;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
namespace Exam
{
public static class Program
{
private static async Task<string> GetWebPage(string uri)
{
var httpClient = new HttpClient();
var response = await httpClient.GetAsync(new Uri(uri, UriKind.Absolute), HttpCompletionOption.ResponseContentRead);
return await response.Content.ReadAsStringAsync();
}
public static void Main(string[] args)
{
try
{
// These two lines do not work - i.e. it terminates the application without any exception being thrown...
//string s = await GetWebPage(@"https://www.dwd.de/DE/leistungen/klimadatendeutschland/klimadatendeutschland.html");
//Console.WriteLine(s);
// This works:
Task<string> getPageTask = GetWebPage(@"https://www.dwd.de/DE/leistungen/klimadatendeutschland/klimadatendeutschland.html");
getPageTask.Wait();
if (getPageTask.IsCompleted)
Console.WriteLine(getPageTask.Result);
}
catch (AggregateException aex)
{
aex.InnerExceptions.AsParallel().ForAll(ex => Console.WriteLine(ex));
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.ReadKey();
}
}
}
When you additionally change the URI to something like @"invalid https://...." you will retrieve the AggregateException.当您另外将 URI 更改为 @"invalid https://...." 之类的内容时,您将检索 AggregateException。 Hope, it helps anyone :-)
希望,它可以帮助任何人:-)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.