.NET Runtime Ошибка 80131506 - Передача лямбда-функции к собственной функции

Итак, я получаю эту ошибку, которая выглядит так, как будто это поврежденная сборка мусора:

Сбой приложения с "внутренней ошибкой в ​​среде выполнения.NET"

Полная ошибка:

Процесс был прерван из-за внутренней ошибки.NET Runtime по IP 71C571C8 (71B20000) с кодом выхода 80131506.

Это работает на:

Версия Framework: 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);

Кажется, что ошибка возникает только после того, как я запустил метод много раз, однако это не происходит последовательно. Иногда это работает, иногда нет.

Любые предложения о том, как это исправить?

1 ответ

Решение

Так что я решил свою проблему с помощью щедрого благотворителя на Discord.

Проблема заключалась в том, что я проходил Lamda чтобы ap / вызвать как делегат:

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

Так что каждый раз, когда unmanagedWinAPI перезвонить моему делегату, 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;
        }

Приложение теперь работает как положено.

Другие вопросы по тегам