C# 从HttpClient.GetAsync()捕获OutOfMemory异常
我正在执行一个相当简单的HttpClient.GetAsync()调用,如果调用的目标存在(它是在本地PC上运行的Web服务),那么我将正确地返回数据,并且一切都按照广告的方式工作。但是,如果调用的目标不存在,我偶尔会抛出OutOfMemory异常。然而,我似乎无法捕捉到这个例外。以下是我打电话的方式: 注意:C# 从HttpClient.GetAsync()捕获OutOfMemory异常,c#,asynchronous,exception,out-of-memory,C#,Asynchronous,Exception,Out Of Memory,我正在执行一个相当简单的HttpClient.GetAsync()调用,如果调用的目标存在(它是在本地PC上运行的Web服务),那么我将正确地返回数据,并且一切都按照广告的方式工作。但是,如果调用的目标不存在,我偶尔会抛出OutOfMemory异常。然而,我似乎无法捕捉到这个例外。以下是我打电话的方式: 注意:proxy只是我已经初始化/创建的类的私有HttpClient成员 public static T get(string methodNameParam) { T returnVal
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;
}
publicstatict-get(stringmethodnameparam)
{
T返回值=默认值(T);
尝试
{
string getString=$“remoteAPI/get/{methodNameParam}”;
HttpResponseMessage response=proxy.GetAsync(getString.Result);
if(响应。IsSuccessStatusCode)
{
字符串jsonString=response.Content.ReadAsStringAsync().Result;
returnValue=JsonConvert.DeserializeObject(jsonString);
}
}
捕获(例外情况除外)
{
//引发日志异常,请允许上级函数对其进行管理。
LogError($“Error Get{methodNameParam}”,ex);
投掷;
}
返回值;
}
OutOfMemory异常从未被捕获,我想是因为它是在异步调用的上下文中抛出的吧?如果只记录发生的异常(当前我的应用程序崩溃和烧坏),我如何捕获该异常
编辑:我根据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;
}
private静态异步任务\u get(string getString)
{
HttpResponseMessage响应=默认值(HttpResponseMessage);
尝试
{
response=wait proxy.GetAsync(getString);
}
捕获(例外情况除外)
{
logger.LogError($“Error(_get)-捕获异常!”,ex);
}
返回响应;
}
公共静态T get(字符串methodNameParam)
{
T返回值=默认值(T);
尝试
{
string getString=$“remoteAPI/get/{methodNameParam}”;
HttpResponseMessage响应=_get(getString).Result;
if(响应。IsSuccessStatusCode)
{
字符串jsonString=response.Content.ReadAsStringAsync().Result;
returnValue=JsonConvert.DeserializeObject(jsonString);
}
}
捕获(例外情况除外)
{
//引发日志异常,请允许上级函数对其进行管理。
LogError($“Error Get{methodNameParam}”,ex);
投掷;
}
返回值;
}
但是,VS19调试器仍然会在调用
\u get()
时,在调用.GetAsync()时捕获同步get()
调用中未处理的内存不足异常
函数被调用。一个OutOfMemoryException
是一个异步异常——您不能保证它会发生在给定的线程上。即使您捕获了它,您的进程也可能处于不一致的状态,因此您最好允许它崩溃,而不是让它几乎肯定会死亡
您最好的策略可能是处理AppDomain.UnhandledException,而不是出于日志记录的目的。请参见
。结果
是坏的m'kay。。。正确的方法是等待任务结果,所以将static T get
更改为static async Task get
,并使用jsonString=wait response.Content.ReadAsStringAsync()
(与GetAsync
的情况相同)“如果调用的目标不存在,我偶尔会抛出OutOfMemory异常”我认为这个假设是错误的。“我实际上似乎无法捕捉到这个异常”我也认为这个假设是错误的,它很可能被捕捉到,但是日志记录不起作用,只是重新刷新。最后,如前所述,不要在异步调用中调用阻塞方法。等待任务。@Selvin,我接受了你的建议,将调用包装在一个异步函数中-这意味着我中断了对.GetAsync()
的调用,并将其放入一个新的异步函数中,该函数不依赖于使用.Result
和调用等待.GetAsync()
。同样的行为也会发生-只要调用.GetAsync()
,同步顶级函数就会在包装异步调用时中断内存不足异常。