If I run the simple method on Unit Test, which generates instances using unmanaged resource, for example bitmap, memory keeps increasing. In the case of executing the method in Thread or ThreadPool, the result is same. But if I run using Task.Run(), GC works properly and memory is not increased.
What is the difference of GC operation between Task.Run and others context?
[TestMethod]
public void Test()
{
//1. GC didn't work.
Work();
//2. GC didn't work.
//new Thread(() =>
//{
// Work();
//}).Start();
//3. GC didn't work.
//ThreadPool.QueueUserWorkItem((obj) =>
//{
// Work();
//});
//4. GC didn't work
//new Action(() =>
//{
// Work();
//}).BeginInvoke(null, null);
//5. GC works.
//Task.Run(() =>
//{
// Work();
//});
Thread.Sleep(Timeout.Infinite);
}
private void Work()
{
while (true)
{
GC.Collect();
var bitmap = new Bitmap(1024, 768);
Thread.Sleep(10);
}
}
First case memory log.
PrivateBytes : 282.0MB, AllHeapsBytes : 3.5MB, Thread Count : 32, CPU Usage : 12% PrivateBytes : 499.0MB, AllHeapsBytes : 2.8MB, Thread Count : 33, CPU Usage : 16% PrivateBytes : 734.0MB, AllHeapsBytes : 2.9MB, Thread Count : 33, CPU Usage : 11% PrivateBytes : 959.0MB, AllHeapsBytes : 3.0MB, Thread Count : 33, CPU Usage : 14% PrivateBytes : 1173.0MB, AllHeapsBytes : 3.1MB, Thread Count : 33, CPU Usage : 10% PrivateBytes : 1389.0MB, AllHeapsBytes : 2.9MB, Thread Count : 33, CPU Usage : 12% PrivateBytes : 1597.0MB, AllHeapsBytes : 2.9MB, Thread Count : 33, CPU Usage : 9% Exception thrown: 'System.ArgumentException' in System.Drawing.dll An exception of type 'System.ArgumentException' occurred in System.Drawing.dll but was not handled in user code Parameter is not valid.
5th case memory log
PrivateBytes : 41.0MB, AllHeapsBytes : 3.5MB, Thread Count : 32, CPU Usage : 16% PrivateBytes : 41.0MB, AllHeapsBytes : 2.9MB, Thread Count : 33, CPU Usage : 13% PrivateBytes : 41.0MB, AllHeapsBytes : 2.9MB, Thread Count : 33, CPU Usage : 14% PrivateBytes : 41.0MB, AllHeapsBytes : 2.9MB, Thread Count : 33, CPU Usage : 12% PrivateBytes : 41.0MB, AllHeapsBytes : 2.9MB, Thread Count : 33, CPU Usage : 14%
--- Updated ---
GC.Collect() doesn't collect immediately. When I call GC.Collect(), the GC will run each object's finalizer on a separate thread.
For GC working immediately, I should add GC.WaitForPendingFinalizers() after calling GC.Collect().
https://www.developer.com/net/csharp/article.php/3343191/C-Tip-Forcing-Garbage-Collection-in-NET.htm
But still I don't understand why GC works in Task.Run context.
--- Updated 2 ---
When I run this code in simple winform project, GC works properly and memory does not grow.
