L
Lighto26
Guest
Hey,
I experience something weird when using EnumThreadWindows
I have this code:
class Program
{
public delegate bool EnumWindowProc(IntPtr hWnd, IntPtr lParam);
[DllImport("user32", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumThreadWindows(int threadId, EnumWindowProc callback, IntPtr lParam);
static void Main(string[] args)
{
var a = true;
while (a)
{
foreach (var process in Process.GetProcesses())
{
foreach (ProcessThread thread in process.Threads)
{
var list = new List<IntPtr>();
EnumThreadWindows(thread.Id, (wnd, param) =>
{
list.Add(wnd);
return true;
}, IntPtr.Zero);
thread.Dispose();
}
process.Dispose();
}
GC.Collect();
Thread.Sleep(1);
}
GC.Collect();
Console.WriteLine("End");
Console.ReadLine();
}
}
When I run this code I can clearly see that my unmanaged memory keep increasing without ever decreasing, even if I stop the while loop and wait, the program's unmanaged memory never decrease
DotMemory screenshot: i.stack.imgur.com/0KlLW.png
So I tried to change my code to use GCHandle.Alloc to pass the list like this:
foreach (ProcessThread thread in process.Threads)
{
var list = new List<IntPtr>();
var aloc = GCHandle.Alloc(list);
var lParam = GCHandle.ToIntPtr(aloc);
EnumThreadWindows(thread.Id, (wnd, param) =>
{
var list1 = GCHandle.FromIntPtr(param).Target as List<IntPtr>;
list1?.Add(wnd);
return true;
}, lParam);
thread.Dispose();
aloc.Free();
}
process.Dispose();
}
When I use GCHandle.Alloc I don't have any memory issues anymore:
i.stack.imgur.com/dga8N.png
The thing is I want to understand why this is happening?
My only idea is that maybe the code inside the EnumWindowProc is unmanaged and when I pass List<IntPtr> which is managed object to the unamanged code it becomes unmanaged and the GC can't clear it anymore.
I may be lacking some understanding of something fundamental so I'd like any explanation
Thanks!
Edit: Sorry about the links for some reason I can't insert links because I need to verify my account, and I already did (Also can't find option to send the email again)
Continue reading...
I experience something weird when using EnumThreadWindows
I have this code:
class Program
{
public delegate bool EnumWindowProc(IntPtr hWnd, IntPtr lParam);
[DllImport("user32", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumThreadWindows(int threadId, EnumWindowProc callback, IntPtr lParam);
static void Main(string[] args)
{
var a = true;
while (a)
{
foreach (var process in Process.GetProcesses())
{
foreach (ProcessThread thread in process.Threads)
{
var list = new List<IntPtr>();
EnumThreadWindows(thread.Id, (wnd, param) =>
{
list.Add(wnd);
return true;
}, IntPtr.Zero);
thread.Dispose();
}
process.Dispose();
}
GC.Collect();
Thread.Sleep(1);
}
GC.Collect();
Console.WriteLine("End");
Console.ReadLine();
}
}
When I run this code I can clearly see that my unmanaged memory keep increasing without ever decreasing, even if I stop the while loop and wait, the program's unmanaged memory never decrease
DotMemory screenshot: i.stack.imgur.com/0KlLW.png
So I tried to change my code to use GCHandle.Alloc to pass the list like this:
foreach (ProcessThread thread in process.Threads)
{
var list = new List<IntPtr>();
var aloc = GCHandle.Alloc(list);
var lParam = GCHandle.ToIntPtr(aloc);
EnumThreadWindows(thread.Id, (wnd, param) =>
{
var list1 = GCHandle.FromIntPtr(param).Target as List<IntPtr>;
list1?.Add(wnd);
return true;
}, lParam);
thread.Dispose();
aloc.Free();
}
process.Dispose();
}
When I use GCHandle.Alloc I don't have any memory issues anymore:
i.stack.imgur.com/dga8N.png
The thing is I want to understand why this is happening?
My only idea is that maybe the code inside the EnumWindowProc is unmanaged and when I pass List<IntPtr> which is managed object to the unamanged code it becomes unmanaged and the GC can't clear it anymore.
I may be lacking some understanding of something fundamental so I'd like any explanation
Thanks!
Edit: Sorry about the links for some reason I can't insert links because I need to verify my account, and I already did (Also can't find option to send the email again)
Continue reading...