【问题标题】:Catching OutOfMemory Exceptions from HttpClient.GetAsync()从 HttpClient.GetAsync() 捕获 OutOfMemory 异常
【发布时间】: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&lt;T&gt; get并使用jsonString = await response.Content.ReadAsStringAsync()(与GetAsync相同)
  • "如果我调用的目标不存在,我偶尔会抛出 OutOfMemory 异常" 我认为这个假设是错误的。 “我实际上似乎无法捕捉到这个异常”我也认为这个假设是错误的,它很可能被捕捉到,但是日志记录不起作用,只是重新抛出。最后如前所述,永远不要在异步调用上调用阻塞方法。等待任务。
  • @Selvin,我接受了你的建议并将调用包装在一个异步函数中——这意味着我中断了对 .GetAsync() 的调用并将其放入一个不依赖于使用 @ 的新异步函数中987654334@ 并在.GetAsync() 上致电await。发生相同的行为 - 只要调用 .GetAsync(),同步顶级函数就会在包装的异步调用处因内存不足异常而中断。

标签: c# asynchronous exception out-of-memory


【解决方案1】:

OutOfMemoryException 是一个异步异常——您不能保证它会在给定线程上发生。即使你抓住了它,你的进程也可能处于不一致的状态,所以你最好让它崩溃而不是拖延它几乎肯定的死亡。

您最好的策略可能是处理AppDomain.UnhandledException,而不是用于记录目的。见https://docs.microsoft.com/en-us/dotnet/api/system.appdomain.unhandledexception?view=net-5.0

【讨论】:

    猜你喜欢
    • 2013-06-01
    • 2016-12-16
    • 1970-01-01
    • 1970-01-01
    • 2015-07-28
    • 2018-06-18
    • 2015-04-25
    • 2016-04-26
    • 2014-07-15
    相关资源
    最近更新 更多