Ошибка выполнения .NET 80131506 - Передача лямбда-функции в собственную функцию - PullRequest
0 голосов
/ 17 сентября 2018

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

Сбой приложения с «внутренней ошибкой в ​​.NET Runtime»

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

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

Выполняетсяon:

Framework 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 Ответ

0 голосов
/ 17 сентября 2018

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

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

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

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

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

...