编程语言
首页 > 编程语言> > c#-.NET运行时错误80131506-将Lambda传递给本机函数

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