Intptr句柄不是垃圾收集

时间:2016-08-08 06:48:00

标签: c#-4.0 garbage-collection pinvoke

原生窗口句柄不是垃圾回收。所以在网上搜索后,我在MSDN文章下面了解了SafeProcessHandle。试图实现它,但我收到'System.Runtime.InteropServices.SEHException'

https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.safehandle.aspx

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;

namespace TestHandle
{
class Program
{
    [DllImport("user32.dll")]
    static extern IntPtr GetForegroundWindow();

    [DllImport("user32.dll")]
    static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);

    [DllImport("user32.dll", SetLastError = true)]
    static extern int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);

    static void Main(string[] args)
    {
        while (true)
        {
            IntPtr hWnd = GetForegroundWindow();

            int processID = 0;
            int threadID = GetWindowThreadProcessId(hWnd, out processID);


            using (Process p = Process.GetProcessById(processID))
            {
                StringBuilder text = new StringBuilder(256);
                GetWindowText(hWnd, text, 256);
                Console.WriteLine(text.ToString());                    
            }

            Console.WriteLine(hWnd);
            Thread.Sleep(100);
        }

        char tmp = 'q';
        while (Console.Read() != tmp) ;
    }
}
}

为了获得当前打开的窗口,我试图通过Timer实现它,并尝试通过while循环,但它增加了内存占用,如果我正在设计一个长时间运行的控制台应用程序,直到PC运行,那么事情正在变得越来越多更差。有人可以帮我吗?

1 个答案:

答案 0 :(得分:0)

GetForegroundWindow返回一个你不需要整理的窗口句柄。问题中显示的代码不会泄漏,也不需要安全的手柄。当您需要整理非托管资源时,可以使用安全句柄。这里情况不同。

如果确实存在泄漏问题,则与显示的代码无关,不需要修改。

<强>更新

关于您的更新,获取进程ID和.net Process对象毫无意义。你不能使用它们。您可以使用窗口句柄请求窗口文本,就像您一样。

这里没有任何内容暗示任何非托管资源泄漏,这里没有任何东西需要安全句柄。如果进程内存使用增长,那么这将是基于GC的进程的正常行为。每次循环循环时,都会创建一个新的StringBuilder对象。

代码可以更简单:

    StringBuilder text = new StringBuilder(256);
    while (true)
    {
        IntPtr hWnd = GetForegroundWindow();
        GetWindowText(hWnd, text, 256);
        Console.WriteLine(text.ToString());
        Console.WriteLine(hWnd);
        Thread.Sleep(100);
    }

请注意,我正在重复使用单个StringBuilder对象,这至少会阻止托管内存使用的稳定增长。

您还应该检查API调用的返回值是否有错误,但我不想在此详细介绍如何执行此操作。