Open theodorzoulias opened 2 years ago
Does this reproduce the problem?
public static async Task Main()
{
Console.WriteLine($"TotalMemory: {GC.GetTotalMemory(true):#,0} bytes");
var lazy = new Nito.AsyncEx.AsyncLazy<int>(GetFunction);
Console.WriteLine($"AsyncLazy result: {await lazy:#,0}");
await Task.Yield();
GC.Collect();
Console.WriteLine($"TotalMemory: {GC.GetTotalMemory(true):#,0} bytes");
GC.KeepAlive(lazy);
static Task<int> GetFunction()
{
byte[] bytes = new byte[20_000_000];
await Task.Delay(200);
return bytes.Length;
}
}
@DaveVdE no, it doesn't. The new byte[20_000_000]
in your example is not captured by a lambda, like in my example. Btw the GetFunction()
in your example returns a Task
, not a Func
, so it's not properly named. It is also missing the async
keyword.
Sure, it's missing the async
keyword, and I didn't change the name.
Oh I see, your point is that the function passed to the AsyncLazy
constructor should be forgotten after the task has been complete.
@DaveVdE yep, as it does the native Lazy<T>
class.
I sent a fix #269.
Description
Hi! I am reporting an issue that I discovered after reading a comment by Servy here. In case the
factory
delegate of anAsyncLazy<T>
instance closes over some expensive resource, this resource will not be eligible for garbage collection after the completion of the delegate.Reproduction Steps
Output:
Online demo.
Expected behavior
The
GC.GetTotalMemory()
after awaiting theAsyncLazy<T>
should be roughly the same as before.Actual behavior
The
GC.GetTotalMemory()
after awaiting theAsyncLazy<T>
is around 20 MB more than before.Configuration
Other information
After switching to a simpler
AsyncLazy<T>
implementation like the one below, the problem is not reproduced:Output: