From b489a3ef58a9e932140b00c039ae831021092ba1 Mon Sep 17 00:00:00 2001 From: Eugene Wang Date: Fri, 23 Nov 2018 16:07:34 -0500 Subject: [PATCH] Fix possible GC'd function pointer in internal msg loop. --- src/NTwain/Threading/WinMsgLoop.cs | 12 ++++++------ src/NTwain/TwainSession.cs | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/NTwain/Threading/WinMsgLoop.cs b/src/NTwain/Threading/WinMsgLoop.cs index a35b5e8..8e848ed 100644 --- a/src/NTwain/Threading/WinMsgLoop.cs +++ b/src/NTwain/Threading/WinMsgLoop.cs @@ -20,10 +20,8 @@ namespace NTwain.Threading static ushort classAtom; static IntPtr hInstance; static readonly uint dequeMsg = UnsafeNativeMethods.RegisterWindowMessageW("WinMsgLoopQueue"); - - const int CW_USEDEFAULT = -1; - - static IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam) + // keep delegate around to prevent GC + static readonly WndProcDelegate WndProc = new WndProcDelegate((hWnd, msg, wParam, lParam) => { Debug.WriteLine($"Dummy window got msg {(WindowMessage)msg}."); switch ((WindowMessage)msg) @@ -33,7 +31,9 @@ namespace NTwain.Threading return IntPtr.Zero; } return UnsafeNativeMethods.DefWindowProcW(hWnd, msg, wParam, lParam); - } + }); + + const int CW_USEDEFAULT = -1; static void InitGlobal() { @@ -45,7 +45,7 @@ namespace NTwain.Threading wc.cbSize = Marshal.SizeOf(wc); wc.style = ClassStyles.CS_VREDRAW | ClassStyles.CS_HREDRAW; - var procPtr = Marshal.GetFunctionPointerForDelegate(new WndProcDelegate(WndProc)); + var procPtr = Marshal.GetFunctionPointerForDelegate(WndProc); wc.lpfnWndProc = procPtr; wc.cbClsExtra = 0; diff --git a/src/NTwain/TwainSession.cs b/src/NTwain/TwainSession.cs index 680f2c7..fc868cf 100644 --- a/src/NTwain/TwainSession.cs +++ b/src/NTwain/TwainSession.cs @@ -23,7 +23,7 @@ namespace NTwain private IntPtr _hWnd; // cache generated twain sources so if you get same source from same session it'll return the same object readonly Dictionary _ownedSources = new Dictionary(); - // need to keep delegate around to prevent GC? + // need to keep delegate around to prevent GC readonly Callback32 _callback32Delegate; // for windows only readonly WinMsgLoop _winMsgLoop;