WebCrawlerの実装に取り組んでいますが、ASP.NETWebAPIのHttpClientで奇妙なメモリリークに直面しています。
したがって、削減されたバージョンはここにあります:
[更新2]
問題を見つけましたが、リークしているのはHttpClientではありません。私の答えを見てください。
[更新1]
効果なしでdisposeを追加しました:
static void Main(string[] args)
{
int waiting = 0;
const int MaxWaiting = 100;
var httpClient = new HttpClient();
foreach (var link in File.ReadAllLines("links.txt"))
{
while (waiting>=MaxWaiting)
{
Thread.Sleep(1000);
Console.WriteLine("Waiting ...");
}
httpClient.GetAsync(link)
.ContinueWith(t =>
{
try
{
var httpResponseMessage = t.Result;
if (httpResponseMessage.IsSuccessStatusCode)
httpResponseMessage.Content.LoadIntoBufferAsync()
.ContinueWith(t2=>
{
if(t2.IsFaulted)
{
httpResponseMessage.Dispose();
Console.ForegroundColor = ConsoleColor.Magenta;
Console.WriteLine(t2.Exception);
}
else
{
httpResponseMessage.Content.
ReadAsStringAsync()
.ContinueWith(t3 =>
{
Interlocked.Decrement(ref waiting);
try
{
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine(httpResponseMessage.RequestMessage.RequestUri);
string s =
t3.Result;
}
catch (Exception ex3)
{
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine(ex3);
}
httpResponseMessage.Dispose();
});
}
}
);
}
catch(Exception e)
{
Interlocked.Decrement(ref waiting);
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(e);
}
}
);
Interlocked.Increment(ref waiting);
}
Console.Read();
}
リンクを含むファイルはここから入手できます。
これにより、メモリが常に上昇します。メモリ分析は、おそらくAsyncCallbackによって保持されている多くのバイトを示しています。私は以前に多くのメモリリーク分析を行いましたが、これはHttpClientレベルのようです。
私はC#4.0を使用しているので、ここではasync / awaitがないため、TPL4.0のみが使用されます。
上記のコードは機能しますが、最適化されておらず、時にはタントラムをスローしますが、効果を再現するには十分です。ポイントは、メモリがリークする原因となるポイントが見つからないことです。