Based on this previous question , I wanted to see if not disposing an HttpClient
object creates leaks (which does, but nothing new here). However, what I've also found is that if I don't dispose a HttpClient
object, the returned HttpResponseMessage
is not garbage collected.
Here's the test. I've provided a reproducing fiddle here .
using System;
using System.Net.Http;
namespace HttpClientTest
{
internal static class Program
{
private static T CallInItsOwnScope<T>(Func<T> getter)
{
return getter();
}
private static void Main()
{
var client = new HttpClient();
var wRef2 = CallInItsOwnScope(() =>
{
using (var response = client.GetAsync(new Uri("https://postman-echo.com/get?foo1=bar1&foo2=bar2")).Result)
{
return new WeakReference(response);
}
});
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine($"Alive: {wRef2.IsAlive}");
client.Dispose();
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine($"Alive: {wRef2.IsAlive}");
Console.ReadKey();
}
}
}
Compiling under .NET Framework 4.7.2, The output is as follows:
Alive: True
Alive: False
Edit: using .NET Core, I get the expected result:
Alive: False
Alive: False
My question is, why HttpResponseMessage
is still alive after I disposed it, but only if I don't dispose it's creator?
(Looking at HttpClient
's sources I found that there is indeed a reference to the HttpResponseMessage
being held, but this is deep into async land for me to really understand what's going on ( SetTaskCompleted
-> TaskCompletionSource<>.TrySetResult()
))
First of all, we need look at this MSDN - HttpClient Class .
HttpClient is intended to be instantiated once per application, rather than per-use. See Remarks.
Anyway, here is what you missed.
public void CallServiceTest()
{
var wRef2 = CallInItsOwnScope(() =>
{
// HttpClient -> HttpMessageInvoker(IDisposable), so it can be disposed.
using (var client = new HttpClient())
{
using (var response = client.GetAsync(new Uri("https://postman-echo.com/get?foo1=bar1&foo2=bar2")).Result)
{
return new WeakReference(response);
}
}
});
GC.Collect();
GC.WaitForPendingFinalizers();
Assert.IsFalse(wRef2.IsAlive);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.