0

我正在使用 win32api 获取所有窗口标题的列表。我需要每隔几秒钟刷新一次列表,这就是问题所在:每次调用EnumWindowsCallback时,应用程序的内存使用量都会增加。

这是一个工作演示: 运行代码并在任务管理器中查看此应用程序的内存使用量如何增加。按 RETURN 再次调用该函数。

Imports System.Runtime.InteropServices
Imports System.Text

Class Example
    Shared Sub Main()
        For a = 1 To 5
            Console.WriteLine("--------- (RUN NR " & a & ") PRESS RETURN")
            Console.ReadLine()
            Win32API.EnumWindowsDllImport(New Win32API.EnumWindowsCallback(AddressOf FillActiveWindowsList), 0)
        Next

        Console.WriteLine("READY!")
        Console.ReadLine()

    End Sub

    Shared Function FillActiveWindowsList(ByVal _hWnd As IntPtr, ByVal lParam As IntPtr) As Boolean
        Dim windowText As New StringBuilder(255)        
        Win32API.GetWindowText(_hWnd, windowText, 255)
        Console.WriteLine(windowText)
        Return True
    End Function

End Class

Public Class Win32API
    Public Delegate Function EnumWindowsCallback(hWnd As Integer, lParam As Integer) As Boolean

    <DllImport("user32.dll", EntryPoint:="EnumWindows", SetLastError:=True, CharSet:=CharSet.Ansi, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
    Public Shared Function EnumWindowsDllImport(callback As EnumWindowsCallback, lParam As Integer) As Integer
    End Function

    <DllImport("user32.dll", EntryPoint:="GetWindowTextA")> _
    Public Shared Sub GetWindowText(hWnd As Integer, lpstring As StringBuilder, nMaxCount As Integer)
    End Sub
End Class

一开始我的 EXE 大约 3MB 大,但在 5 次函数调用后它增加到 6 MB(并保持在那里)问题是如果内存使用量超过 6 MB,它会在我的主应用程序中导致一些崩溃。上面的例子不应该崩溃。

你看到这里有问题吗?也许数据类型有问题?或者它可能是一个错误?任何帮助,将不胜感激。

4

2 回答 2

2

这是不可能的,在您消耗至少 1500 MB 之前,您不会收到 OutOfMemoryException。从解释泄漏的“崩溃”中删除了 x250 的因素。3 MB 的增加只是垃圾收集堆的增长以满足您的程序需求。看到它稳定也是完全正常的,最终暗示你没有泄漏。

当然,您可以获得比“它崩溃”更好的诊断。您的代码中确实存在错误,pinvoke 声明是错误的。lParam 参数是 IntPtr,而不是 int。这可能会导致不同程度的动荡,您通常会从 PInvokeStackImbalance 托管调试器助手那里收到警告。使用 pinvoke.net 网站获得更好的。如果您需要更多帮助,请在调试器中详细显示“崩溃”的样子。

于 2013-11-11T21:22:00.893 回答
0

替换此代码

For a = 1 To 5
    Console.WriteLine("--------- (RUN NR " & a & ") PRESS RETURN")
    Console.ReadLine()
    Win32API.EnumWindowsDllImport(New Win32API.EnumWindowsCallback(AddressOf FillActiveWindowsList), 0)
Next

使用此代码

dim a as integer = 1
DoitFive:
Console.WriteLine("--------- (RUN NR " & a & ") PRESS RETURN")
Console.ReadLine()
Win32API.EnumWindowsDllImport(New Win32API.EnumWindowsCallback(AddressOf FillActiveWindowsList), 0)
a += 1
if a <> 5 then goto DoitFive

因为您使用的代码将执行您的 EXE 进程,直到循环 5 次,这将使其大​​小为 6MB。

于 2014-10-02T18:11:13.613 回答