【发布时间】:2020-12-28 19:21:24
【问题描述】:
问题:在长时间正确使用 HttpClient(作为静态单个实例)后,ConcurrentStack+Node 实例的大小持续增长,导致内存使用量增加。
编辑:这似乎与 SetText 和 AddText 中调用的调度程序有关。
用例:我正在通过 HTTP 传输轮询本地网络上的设备。我使用 System.Threading.Timer 来控制我的请求频率。轮询计时器的回调是 async void,因此 await 运算符可用于继续控制。默认窗口调度器用于在调用 HttpRequest 后显示文本结果。
娱乐代码:.NET Framework 4.5; WPF ;在 MainWindow 中使用 x:Name="Debug"
创建的单个 TextBlock 的所有标准设置 using System;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
namespace LeakIsolator
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
static MainWindow()
{
WebClient.CachePolicy = new System.Net.Cache.RequestCachePolicy(System.Net.Cache.RequestCacheLevel.NoCacheNoStore);
HttpClient.DefaultRequestHeaders.CacheControl = new System.Net.Http.Headers.CacheControlHeaderValue()
{
NoStore = true,
NoCache = true
};
}
public MainWindow()
{
InitializeComponent();
Timer = new Timer(Poll, null, Timeout.Infinite, Timeout.Infinite);
Loaded += MainWindow_Loaded;
}
private static HttpClient HttpClient { get; } = new HttpClient();
private static WebClient WebClient { get; } = new WebClient();
private Timer Timer { get; }
private void SetText(string text)
{
Dispatcher.Invoke(() => Debug.Text = text);
}
private void AddText(string text)
{
Dispatcher.Invoke(() => Debug.Text += text);
}
private async void Poll(object a)
{
try
{
SetText("Getting status...");
SetText(await GetResponseStringHttpClient("http://10.10.10.87/status"));
}
catch (Exception e)
{
SetText($"Exception. {e.Message}");
}
finally
{
Start();
}
}
private async Task<string> GetResponseStringWebClient(string address)
{
return await WebClient.DownloadStringTaskAsync(address);
}
private async Task<string> GetResponseStringHttpClient(string address)
{
using (var response = await HttpClient.GetAsync(address))
{
if (response.IsSuccessStatusCode)
{
AddText(" Success...");
return await response.Content.ReadAsStringAsync();
}
else
{
AddText(" Fail.");
return null;
}
}
}
private void Start()
{
Timer.Change(1000, Timeout.Infinite);
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
Start();
}
}
}
使用 ANTS 内存分析器,并在最近的测试中运行应用程序 37 分钟,2.618 MB(现在很小,但这是一个长时间运行的应用程序)无法访问的字节由 PinnableBufferCache 分配,大概存储在第 2 代堆中。
我不确定这是内存泄漏还是我不理解的部分内容。为什么我看到这些内存增加,为什么我无法指定 HttpClient 和 WebClient 的本地缓存行为?
【问题讨论】:
-
Debug.Text += text肯定会使用越来越多的内存,因为TextBlock的内容会越来越长。这也可能不是添加到TextBlock的最有效方式,您可以尝试Debug.Inlines.Add(text);
标签: c# .net memory-leaks