【发布时间】:2020-11-13 00:43:31
【问题描述】:
我正在执行一个相当简单的 HttpClient.GetAsync() 调用,如果我的调用目标存在(它是在我的本地 PC 上运行的 Web 服务),那么我可以正确地取回数据并且一切都按照宣传的那样工作。但是,如果我调用的目标不存在,我偶尔会抛出 OutOfMemory 异常。然而,我实际上似乎无法捕捉到这个异常。以下是我拨打电话的方式:
注意:proxy 只是我的类的私有 HttpClient 成员,它已经被初始化/创建。
public static T get(string methodNameParam)
{
T returnValue = default(T);
try
{
string getString = $"remoteAPI/get/{methodNameParam}";
HttpResponseMessage response = proxy.GetAsync(getString).Result;
if(response.IsSuccessStatusCode)
{
String jsonString = response.Content.ReadAsStringAsync().Result;
returnValue = JsonConvert.DeserializeObject<T>(jsonString);
}
}
catch (Exception ex)
{
// log exception thrown, allow upper functions to manage it.
logger.LogError($"Error Get {methodNameParam} ", ex);
throw;
}
return returnValue;
}
OutOfMemory 异常从未被捕获,我假设是因为它是在 Async 调用的上下文中抛出的?如果只是记录它发生的情况(当前我的应用程序崩溃和烧毁),我如何才能捕获此异常。
编辑:我根据 Selvin 的反馈更新了函数,现在看起来像:
private static async Task<HttpResponseMessage> _get(string getString)
{
HttpResponseMessage response = default(HttpResponseMessage);
try
{
response = await proxy.GetAsync(getString);
}
catch (Exception ex)
{
logger.LogError($"Error (_get) - Caught Exception! ", ex);
}
return response;
}
public static T get(string methodNameParam)
{
T returnValue = default(T);
try
{
string getString = $"remoteAPI/get/{methodNameParam}";
HttpResponseMessage response = _get(getString).Result;
if(response.IsSuccessStatusCode)
{
String jsonString = response.Content.ReadAsStringAsync().Result;
returnValue = JsonConvert.DeserializeObject<T>(jsonString);
}
}
catch (Exception ex)
{
// log exception thrown, allow upper functions to manage it.
logger.LogError($"Error Get {methodNameParam} ", ex);
throw;
}
return returnValue;
}
但是,一旦调用了.GetAsync() 函数,VS19 调试器仍然会在调用_get() 时捕获同步get() 调用中未处理的内存不足异常。
【问题讨论】:
-
.Result不好吗? ...正确的方法是等待任务结果,因此将static T get更改为static async Task<T> get并使用jsonString = await response.Content.ReadAsStringAsync()(与GetAsync相同) -
"如果我调用的目标不存在,我偶尔会抛出 OutOfMemory 异常" 我认为这个假设是错误的。 “我实际上似乎无法捕捉到这个异常”我也认为这个假设是错误的,它很可能被捕捉到,但是日志记录不起作用,只是重新抛出。最后如前所述,永远不要在异步调用上调用阻塞方法。等待任务。
-
@Selvin,我接受了你的建议并将调用包装在一个异步函数中——这意味着我中断了对
.GetAsync()的调用并将其放入一个不依赖于使用 @ 的新异步函数中987654334@ 并在.GetAsync()上致电await。发生相同的行为 - 只要调用.GetAsync(),同步顶级函数就会在包装的异步调用处因内存不足异常而中断。
标签: c# asynchronous exception out-of-memory