Nie czuję się w żadnym razie ekspertem od zarządzania pamiecią w aplikacjach .NET, ale poniższy kod pomógł mi funkcjonowaniu jednej z moich aplikacji. Co prawda poniższy kod nie pokazuje dokładnie tej wartości, która jest pokazywana w Task Manager, ale jest bliska prawdy. Tak przynajmniej wynika z moich empirycznych doświadczeń.
1: string GetMemoryUsage() {
2: try {
3: Application.DoEvents();
4: Process p = Process.GetCurrentProcess();
5: if (p != null) {
6: return FormatBytes(p.WorkingSet64);
7: }
8: }
9: catch { }
10:
11: return String.Empty;
12:
13: }
1: [System.Diagnostics.DebuggerStepThrough()]
2: string FormatBytes(long bytes) {
3: const int scale = 1024;
4: string[] orders = new string[] { "GB", "MB", "KB", "b" };
5: long max = (long)Math.Pow(scale, orders.Length - 1);
6:
7: foreach (string order in orders) {
8: if (bytes > max)
9: {
10: return string.Format("{0:##.##} {1}",
11: decimal.Divide(bytes, max), order);
12: }
13: max /= scale;
14: }
15: return "0 b";
16: }
W ceu odzyskania części pamięci korzystam z funkcji SetProcessWorkingSetSize z Kernel32.dll
1: [DllImport("KERNEL32.DLL",
2: EntryPoint="SetProcessWorkingSetSize",
3: SetLastError=true,
4: CallingConvention=CallingConvention.StdCall)]
5: internal static extern bool SetProcessWorkingSetSize(
6: IntPtr pProcess,
7: int dwMinimumWorkingSetSize,
8: int dwMaximumWorkingSetSize);
9:
10: internal void ClearMemory() {
11: Application.DoEvents();
12: try {
13: System.Diagnostics.Process p =
14: System.Diagnostics.Process.GetCurrentProcess();
15: if (p != null) {
16: IntPtr pHandle = p.Handle;
17: if (pHandle != IntPtr.Zero) {
18: SetProcessWorkingSetSize(pHandle, -1, -1);
19: }
20: }
21: }
22: catch { }
23:
24: GC.Collect();
25: GC.WaitForPendingFinalizers();
26: }