diff --git a/src/Windows/Avalonia.Win32/Input/WindowsInputPane.cs b/src/Windows/Avalonia.Win32/Input/WindowsInputPane.cs index 79e67ecc82..a639c05844 100644 --- a/src/Windows/Avalonia.Win32/Input/WindowsInputPane.cs +++ b/src/Windows/Avalonia.Win32/Input/WindowsInputPane.cs @@ -52,6 +52,11 @@ internal unsafe class WindowsInputPane : InputPaneBase, IDisposable private void OnStateChanged(bool showing, UnmanagedMethods.RECT? prcInputPaneScreenLocation) { + // Unadvise can deliver last notification while it unwinds, and the shell can call back after teardown. + // Either would dereference a disposed _windowImpl, crashing the process. + if (_disposed) + return; + var oldState = (OccludedRect, State); OccludedRect = prcInputPaneScreenLocation.HasValue ? ScreenRectToClient(prcInputPaneScreenLocation.Value) @@ -76,7 +81,6 @@ internal unsafe class WindowsInputPane : InputPaneBase, IDisposable if (_disposed) return; _disposed = true; - _windowImpl = null!; if (_inputPane is not null) { if (_cookie != 0) @@ -87,6 +91,11 @@ internal unsafe class WindowsInputPane : InputPaneBase, IDisposable _inputPane.Dispose(); _inputPane = null; } + + // Released only once Unadvise has returned, so the field stays valid for the whole of the + // teardown it is read during. + _windowImpl = null!; + // Suppress finalization. GC.SuppressFinalize(this); }