From fc9679491a1a395a6c24316a3bbbf24336bab85f Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Thu, 9 Jul 2026 20:53:48 +0500 Subject: [PATCH] Fixes a dispatcher bug that loses background processing state if jobs were submitted before ReplaceImplementation (#21735) --- src/Avalonia.Base/Threading/Dispatcher.cs | 3 ++ .../DispatcherTests.cs | 32 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/src/Avalonia.Base/Threading/Dispatcher.cs b/src/Avalonia.Base/Threading/Dispatcher.cs index 4f3acc5d02..04ea63e9e4 100644 --- a/src/Avalonia.Base/Threading/Dispatcher.cs +++ b/src/Avalonia.Base/Threading/Dispatcher.cs @@ -162,6 +162,9 @@ public partial class Dispatcher : IDispatcher _backgroundProcessingImpl.ReadyForBackgroundProcessing += OnReadyForExplicitBackgroundProcessing; if (_signaled) _impl.Signal(); + if (_explicitBackgroundProcessingRequested) + _backgroundProcessingImpl?.RequestBackgroundProcessing(); + _osTimerSetTo = null; UpdateOSTimer(); } diff --git a/tests/Avalonia.Base.UnitTests/DispatcherTests.cs b/tests/Avalonia.Base.UnitTests/DispatcherTests.cs index 03c8133b74..d4e39d34b6 100644 --- a/tests/Avalonia.Base.UnitTests/DispatcherTests.cs +++ b/tests/Avalonia.Base.UnitTests/DispatcherTests.cs @@ -151,6 +151,38 @@ public partial class DispatcherTests Assert.Equal(new[] { "PromotedRender", "PromotedRender2", "Render" }, actions); } + [Fact] + public void DispatcherRepeatsBackgroundProcessingRequestToTheNewImplementation() + { + var actions = new List(); + + // Requests background processing from the pre-initialization implementation + _uiThread.Post(() => actions.Add("Background"), DispatcherPriority.Background); + + var impl = new SimpleDispatcherWithBackgroundProcessingImpl(); + Dispatcher.InitializeUIThreadDispatcher(impl); + + Assert.True(impl.AskedForBackgroundProcessing); + impl.FireBackgroundProcessing(); + Assert.Equal(new[] { "Background" }, actions); + } + + [Fact] + public void DispatcherRepeatsSignalToTheNewImplementation() + { + var actions = new List(); + + // Signals the pre-initialization implementation + _uiThread.Post(() => actions.Add("Render"), DispatcherPriority.Render); + + var impl = new SimpleDispatcherWithBackgroundProcessingImpl(); + Dispatcher.InitializeUIThreadDispatcher(impl); + + Assert.True(impl.AskedForSignal); + impl.ExecuteSignal(); + Assert.Equal(new[] { "Render" }, actions); + } + [Fact] public void DispatcherStopsItemProcessingWhenInteractivityDeadlineIsReached() {