Home > front end >  C#/Win32: WNDPROC is invoked after being garbage-collected
C#/Win32: WNDPROC is invoked after being garbage-collected

Time:12-11

I'm writing a cross-platform emulator frontend using Eto.Forms in C#. The emulator backend requires a native window to display its output to, and thus, I need to write native controls wrapping said native windows.

To create a WinAPI window, I need to create and register a window class, which I do like this (imports and static imports removed for clarity):

    static unsafe Win32SubWindow()
    {
        _refWndProc = WindowProc;

        fixed (char* pWindowClass = WINDOW_CLASS)
        {
            WNDCLASSEXW wndClass = new()
            {
                cbSize = (uint) Marshal.SizeOf<WNDCLASSEXW>(),
                style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW,
                lpfnWndProc = _refWndProc,
                cbClsExtra = 0,
                cbWndExtra = 0,
                hInstance = CurrentHInstanceRaw,
                hIcon = HICON.Null,
                hCursor = LoadCursor(HINSTANCE.Null, IDC_ARROW),
                hbrBackground = HBRUSH.Null,
                lpszMenuName = null,
                lpszClassName = pWindowClass,
                hIconSm = HICON.Null
            };

            RegisterClassEx(in wndClass);
        }
    }

    internal static readonly WNDPROC _refWndProc;

The _refWndProc variable should keep the delegate alive until the program ends, but I'm met with this error when I close my window:

Process terminated. A callback was made on a garbage collected delegate of type 'M64RPFW.Wpf!Windows.Win32.UI.WindowsAndMessaging.WNDPROC::Invoke'.
Repeat 3 times:
--------------------------------
   at MS.Win32.UnsafeNativeMethods.CallWindowProc(IntPtr, IntPtr, Int32, IntPtr, IntPtr)
   at MS.Win32.UnsafeNativeMethods.CallWindowProc(IntPtr, IntPtr, Int32, IntPtr, IntPtr)
   at MS.Win32.HwndSubclass.DefWndProcWrapper(IntPtr, Int32, IntPtr, IntPtr)
   at MS.Win32.UnsafeNativeMethods.CallWindowProc(IntPtr, IntPtr, Int32, IntPtr, IntPtr)
   at MS.Win32.UnsafeNativeMethods.CallWindowProc(IntPtr, IntPtr, Int32, IntPtr, IntPtr)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr, Int32, IntPtr, IntPtr)
--------------------------------
   at MS.Win32.UnsafeNativeMethods.DispatchMessage(System.Windows.Interop.MSG ByRef)
   at MS.Win32.UnsafeNativeMethods.DispatchMessage(System.Windows.Interop.MSG ByRef)
   at System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame)
   at System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame)
   at System.Windows.Threading.Dispatcher.Run()
   at System.Windows.Application.RunDispatcher(System.Object)
   at System.Windows.Application.RunInternal(System.Windows.Window)
   at System.Windows.Application.Run(System.Windows.Window)
   at Eto.Wpf.Forms.ApplicationHandler.Run()
   at Eto.Forms.Application.Run()
   at M64PRR.Wpf.Program.Main(System.String[])

What could cause Win32SubWindow._refWndProc to be garbage-collected while it is still in use? Other SO questions I've found have been solved by maintaining a reference to the delegate.

CodePudding user response:

The error was caused by a different instance of WNDPROC than the one mentioned here. My application also uses a helper window to help initialize OpenGL, and moving that window's WNDPROC to a variable solved the issue.

  • Related