所以我收到这个错误,看起来好像是一个损坏的垃圾收集:
Application Crashes With "Internal Error In The .NET Runtime"
完整的错误是:
The process was terminated due to an internal error in the .NET Runtime at IP 71C571C8 (71B20000) with exit code 80131506.
它正在运行:
Framework Version: v4.0.30319
重复运行此函数时会出现这种情况:
public static int GetMdiTitledChildWindows(IntPtr parentWindow)
{
IntPtr mdiClient = FindWindowEx(parentWindow, IntPtr.Zero, MdiClient, "");
List<IntPtr> handles = new List<IntPtr>();
EnumChildWindows(mdiClient, (hwnd, param) =>
{
handles.Add(hwnd);
return true;
}, IntPtr.Zero);
int counter = 0;
foreach (IntPtr handle in handles)
{
StringBuilder builder = new StringBuilder();
GetWindowText(handle, builder, GetWindowTextLength(handle)+1);
if (builder.Length > 0)
{
counter++;
}
}
return counter;
}
其中 FindWindowEx()
、EnumChildWindows()
和 GetWindowText()
都是 p/invoke 签名,定义与此类似:
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam);
错误似乎只在我多次运行该方法后才会发生,但是,这种情况不会一直发生。有时有效,有时无效。
关于如何解决这个问题有什么建议吗?
最佳答案
所以我在 Discord 上一位慷慨的捐助者的帮助下解决了我的问题。
问题是我将 lambda 作为委托(delegate)传递给 p/invoke:
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam);
因此,每次非托管 WinAPI 调用回调到我的委托(delegate)中时,GC 都有机会运行,如果运行的话,它会收集我的 lambda,从而导致这次崩溃。这不一定会发生,这就是为什么我的方法大部分时间都有效并且不一致地崩溃的原因。
解决方案是添加对 lambda 的引用,以防止 GC 收集它(尽管我全力以赴并将其设为本地函数,因为皮带和大括号):
public static int GetMdiTitledChildWindows(IntPtr parentWindow)
{
IntPtr mdiClient = FindWindowEx(parentWindow, IntPtr.Zero, MdiClient, "");
List<IntPtr> handles = new List<IntPtr>();
bool addToList(IntPtr hwnd, IntPtr param)
{
handles.Add(hwnd);
return true;
}
EnumWindowsProc gcHolder = addToList;
EnumChildWindows(mdiClient, gcHolder, IntPtr.Zero);
int counter = 0;
foreach (IntPtr handle in handles)
{
int textLength = GetWindowTextLength(handle) + 1;
StringBuilder builder = new StringBuilder(textLength);
GetWindowText(handle, builder, textLength);
if (builder.Length > 0)
{
counter++;
}
}
return counter;
}
应用程序现在按预期运行。
关于c# - .NET 运行时错误 80131506 - 将 Lambda 传递给 native 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52360046/