From e4c1e68582ea19b6163438eece0402588186ce39 Mon Sep 17 00:00:00 2001 From: Eugene Wang <8755753+soukoku@users.noreply.github.com> Date: Tue, 3 Feb 2026 18:31:54 -0500 Subject: [PATCH] More correct cleanup of message pump. --- src/NTwain/Platform/Win32MessagePump.cs | 46 ++++++++++++------------- src/NTwain/TwainAppSession.cs | 1 - 2 files changed, 22 insertions(+), 25 deletions(-) diff --git a/src/NTwain/Platform/Win32MessagePump.cs b/src/NTwain/Platform/Win32MessagePump.cs index 9696d09..0bb5be5 100644 --- a/src/NTwain/Platform/Win32MessagePump.cs +++ b/src/NTwain/Platform/Win32MessagePump.cs @@ -20,14 +20,13 @@ namespace NTwain.Platform; #if !NETFRAMEWORK [SupportedOSPlatform("windows5.1.2600")] #endif -internal sealed class Win32MessagePump : IDisposable +internal sealed class Win32MessagePump { private const uint WM_APP_INVOKE = PInvoke.WM_APP + 1; private readonly FreeLibrarySafeHandle _hInstance; private readonly uint _threadId; private HWND _mainWindow; - private bool _disposed; // Store the delegate to prevent garbage collection private WNDPROC _wndProc; // Instance field, not static @@ -107,17 +106,28 @@ internal sealed class Win32MessagePump : IDisposable UnregisterWindowClass(); return -1; } - - // Create and install the SynchronizationContext + _synchronizationContext = new Win32SynchronizationContext(this); SynchronizationContext.SetSynchronizationContext(_synchronizationContext); - int exitCode = RunMessageLoop(); + int exitCode; + try + { + exitCode = RunMessageLoop(); + } + finally + { + if (!_mainWindow.IsNull) + { + PInvoke.DestroyWindow(_mainWindow); + _mainWindow = HWND.Null; + } - // Clear the SynchronizationContext - SynchronizationContext.SetSynchronizationContext(null); + UnregisterWindowClass(); - Dispose(); + SynchronizationContext.SetSynchronizationContext(null); + _synchronizationContext = null; + } return exitCode; } @@ -257,6 +267,8 @@ internal sealed class Win32MessagePump : IDisposable /// public void PostToUIThread(Action action) { + if (_mainWindow.IsNull) throw new InvalidOperationException("Message pump main window is not available."); + if (InvokeRequired) { lock (_workQueueLock) @@ -280,6 +292,8 @@ internal sealed class Win32MessagePump : IDisposable /// public void Quit(int exitCode = 0) { + if (_mainWindow.IsNull) throw new InvalidOperationException("Message pump main window is not available."); + if (InvokeRequired) { PostToUIThread(() => @@ -345,22 +359,6 @@ internal sealed class Win32MessagePump : IDisposable return PInvoke.DefWindowProc(hwnd, msg, wParam, lParam); } - - public void Dispose() - { - if (_disposed) - return; - - _disposed = true; - - if (!_mainWindow.IsNull) - { - PInvoke.DestroyWindow(_mainWindow); - _mainWindow = HWND.Null; - } - - UnregisterWindowClass(); - } } /// diff --git a/src/NTwain/TwainAppSession.cs b/src/NTwain/TwainAppSession.cs index 65244e9..45662c6 100644 --- a/src/NTwain/TwainAppSession.cs +++ b/src/NTwain/TwainAppSession.cs @@ -132,7 +132,6 @@ public partial class TwainAppSession : IDisposable { _twainPumpForWin.RemoveMessageFilter(this); _twainPumpForWin.Quit(); - _twainPumpForWin.Dispose(); } if (_procEvent.pEvent != IntPtr.Zero)