UWP C# Windows.Web.HttpClient 内存泄漏

UWP C# Windows.Web.HttpClient memory leak

我需要定期向网站发送 GET 请求。

protected override async void OnNavigatedTo(NavigationEventArgs e)
{
   base.OnNavigatedTo(e);

   HttpClient httpClient = new HttpClient();
   Uri requestUri = new Uri("https://pastebin.com/raw/1j9EAVUW");

   while (true)
   {
      await httpClient.GetAsync(requestUri);
      await Task.Delay(1000);
   }
}

但是,运行此代码会导致内存泄漏,并且 RAM 使用率每秒都在增加。

应用using没有任何帮助,也没有在循环内初始化HttpClient

我想出的唯一解决方案是手动调用 GC.Collect() 每次循环执行,或每~10 次执行。但我读到它被认为是一种不好的做法。

还有其他方法吗?

HttpClient 文档:https://docs.microsoft.com/en-us/uwp/api/windows.web.http.httpclient?view=winrt-19041

我认为这不是内存泄漏。正如评论中所指出的,调用 GC.Collect() 正在释放内存这一事实意味着这里没有问题。垃圾收集器在 .Net 中的工作方式太 long/complicated 无法在此解释,但要记住的是,收集垃圾并不是一项廉价操作。事实上,GC 可能不得不在收集时暂停线程,因此 .Net 将尝试在收集之前等待,即使那样它也取决于系统当前的内存压力。

另一件需要注意的事情是,调用 ````GetAsync(Uri)``` 实际上会在 returning 之前下载整个 HTTP 响应,这意味着它可能正在分配内存来保存 HTTP 响应。这是 GetASync 文档中的备注部分:

This operation will not block. The returned IAsyncOperationWithProgress (of HttpResponseMessage and HttpProgress) completes after the **whole response (including content) is read.**

如果您不需要这些内容,您可以在读取响应 headers 后告诉 HttpClient return 来减少分配(这样它就不会为 body 的响应),您还可以处理响应 object 释放任何已使用的资源:

var response = await httpClient.GetAsync("http://example.com", HttpCompletionOption.ResponseHeadersRead);
response.Dispose();

不用担心添加 GC.Collect()...将其留给 .Net/GC 来确定何时需要它。

当您在 using 语句中使用 HttpClient 实例时,一旦执行退出 using 语句的范围,将自动调用 HttpClient.Dispose() 以释放系统资源.高 RAM 消耗是因为垃圾收集没有及时收集释放的资源。但是垃圾收集会在需要时收集释放的资源,例如分配其他对象或内存不足。您可以通过打开多个 Visual Studio 解决方案来测试它,垃圾收集将收集从 HttpClient 个实例中释放的资源。

如果你想让垃圾收集器积极地收集释放的资源,你可以将GCCollectionMode设置为Optimized,它指示垃圾收集器只有在以下情况下才开始收集它确定该集合的生产力足以证明是合理的。

您可以参考 document.

获得有关提高垃圾收集性能的更多信息