.NET运行时错误80131506-将Lambda传递给本机函数 [英] .NET Runtime Error 80131506 - Passing Lambda to Native Function

查看:357
本文介绍了.NET运行时错误80131506-将Lambda传递给本机函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我收到了一个看起来好像是垃圾回收已损坏的错误:

应用程序因".NET内部错误"而崩溃运行时"

完整错误是:

由于.NET运行时IP 71C571C8(71B20000)的内部错误,退出代码为80131506,该过程被终止.

它正在运行:

框架版本: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);

因此,每当unmanaged 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;
        }

该应用程序现在可以正常运行了.

So I'm getting this error that looks as though it's a corrupted garbage collection:

Application Crashes With "Internal Error In The .NET Runtime"

The full error is:

The process was terminated due to an internal error in the .NET Runtime at IP 71C571C8 (71B20000) with exit code 80131506.

It's running on:

Framework Version: v4.0.30319

This occurs inconsistently when running this function repeatedly:

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;
        }

Where FindWindowEx(), EnumChildWindows() and GetWindowText() are all p/invoke signatures defined similarly to this:

[DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam);

The error only seems to occur after I've run the method many times, however, this doesn't happen consistently. Sometimes it works, sometimes it doesn't.

Any suggestions on how to fix this?

解决方案

So I solved my issue with the help of a generous benefactor on Discord.

The problem was that I was passing a Lamda to a p/invoke as a delegate:

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam);

So every time the unmanaged WinAPI call called-back into my delegate, the GC had the opportunity to run, if it did, it collected my lamda causing this crash. This wouldn't necessarily happen, hence why my method worked most of the time and crashed inconsistently.

The solution was to add a reference to the lamda that would prevent the GC from collecting it (although I went whole-hog and made it a local function because belt and braces):

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;
        }

The application now works as expected.

这篇关于.NET运行时错误80131506-将Lambda传递给本机函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆