我正在使用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,它会导致我的主应用程序中的一些崩溃。上面的例子不应该崩溃。
你知道这里有问题吗?也许数据类型有问题?或者它可能是一个错误?任何帮助将不胜感激。答案 0 :(得分:2)
这是不可能的,在消耗至少1500 MB之前,你不会得到OutOfMemoryException。从解释泄漏的“崩溃”中删除了x250的因素。 3 MB的增长只是垃圾收集堆的增长,以满足您的程序的需求。看到它稳定也是完全正常的,这是你没有泄漏的最终暗示。
当然,你会获得更好的诊断,而不仅仅是“崩溃”。您的代码中确实存在错误,pinvoke声明是错误的。 lParam参数是IntPtr,而不是int。这可能会导致各种剧变,您通常会从PInvokeStackImbalance托管调试器助手收到警告。使用pinvoke.net网站获得更好的网站。如果您需要更多帮助,请详细显示调试器中“崩溃”的样子。
答案 1 :(得分: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。