c#-.NET运行时错误80131506-将Lambda传递给本机函数
作者:互联网
所以我收到这个错误,看起来好像是一个损坏的垃圾回收:
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的慷慨捐助者的帮助下解决了我的问题.
问题是我将Lamda作为委托传递给p / invoke:
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam);
因此,每次非托管WinAPI调用回调到我的委托中时,GC都有机会运行,如果这样做,它将收集我的lamda导致崩溃.这不一定会发生,因此为什么我的方法在大多数情况下都有效并且崩溃不一致.
解决的办法是在lamda上添加一个引用,以防止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;
}
该应用程序现在可以按预期工作.
标签:winapi,c,net,pinvoke,garbage-collection 来源: https://codeday.me/bug/20191108/2008819.html