Skip to content

Commit 2849267

Browse files
authored
Merge pull request #21317 from ramezgerges/nativedispatcher_always_enqueue_on_normal
fix(nativedispatchersynchronizationcontext): always enqueue on Normal
2 parents 2606ab9 + 360f95b commit 2849267

File tree

10 files changed

+33
-43
lines changed

10 files changed

+33
-43
lines changed

src/Uno.UI.Dispatching/Native/NativeDispatcher.cs

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@ internal sealed partial class NativeDispatcher
3131
new Queue<Delegate>(), // Idle
3232
};
3333

34-
private readonly NativeDispatcherSynchronizationContext[] _synchronizationContexts;
35-
3634
private readonly object _gate = new();
3735

3836
private readonly long _startTime;
@@ -57,30 +55,14 @@ private NativeDispatcher()
5755

5856
_currentPriority = NativeDispatcherPriority.Normal;
5957

60-
_synchronizationContexts = new NativeDispatcherSynchronizationContext[]
61-
{
62-
new(this, NativeDispatcherPriority.High),
63-
new(this, NativeDispatcherPriority.Normal),
64-
new(this, NativeDispatcherPriority.Low),
65-
new(this, NativeDispatcherPriority.Idle),
66-
};
58+
SynchronizationContext = new NativeDispatcherSynchronizationContext(this);
6759

6860
Initialize();
6961

7062
_startTime = Stopwatch.GetTimestamp();
7163
}
7264

73-
/// <summary>
74-
/// Gets the synchronizations contexts for the available priorities from <see cref="NativeDispatcherPriority"/>.
75-
/// </summary>
76-
internal NativeDispatcherSynchronizationContext GetSynchronizationContext(NativeDispatcherPriority priority)
77-
{
78-
if ((int)priority < 0 || (int)priority > 3)
79-
{
80-
throw new ArgumentOutOfRangeException(nameof(priority));
81-
}
82-
return _synchronizationContexts[(int)priority];
83-
}
65+
internal NativeDispatcherSynchronizationContext SynchronizationContext { get; }
8466

8567
/// <summary>
8668
/// Enforce access on the UI thread.
@@ -148,7 +130,7 @@ private static void RunAction(NativeDispatcher dispatcher, Action? action)
148130
{
149131
try
150132
{
151-
using (dispatcher._synchronizationContexts[(int)dispatcher._currentPriority].Apply())
133+
using (dispatcher.SynchronizationContext.Apply())
152134
{
153135
action();
154136
}

src/Uno.UI.Dispatching/Native/NativeDispatcherSynchronizationContext.cs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,21 @@
33
namespace Uno.UI.Dispatching
44
{
55
/// <summary>
6-
/// Provides a CoreDispatched Synchronization context, to allow for async methods to keep the dispatcher priority.
6+
/// A synchronization context that always schedules on the Normal priority.
77
/// </summary>
88
internal sealed class NativeDispatcherSynchronizationContext : SynchronizationContext
99
{
1010
private readonly NativeDispatcher _dispatcher;
11-
private readonly NativeDispatcherPriority _priority;
11+
private const NativeDispatcherPriority Priority = NativeDispatcherPriority.Normal;
1212

13-
public NativeDispatcherSynchronizationContext(NativeDispatcher dispatcher, NativeDispatcherPriority priority)
13+
public NativeDispatcherSynchronizationContext(NativeDispatcher dispatcher)
1414
{
1515
_dispatcher = dispatcher;
16-
_priority = priority;
1716
}
1817

1918
public override void Post(SendOrPostCallback d, object state)
2019
{
21-
_dispatcher.Enqueue(() => d(state), _priority);
20+
_dispatcher.Enqueue(() => d(state), Priority);
2221
}
2322

2423
public override void Send(SendOrPostCallback d, object state)
@@ -30,7 +29,7 @@ public override void Send(SendOrPostCallback d, object state)
3029
else
3130
{
3231
_dispatcher
33-
.EnqueueAsync(() => d(state), _priority)
32+
.EnqueueAsync(() => d(state), Priority)
3433
.Wait();
3534
}
3635
}

src/Uno.UI.Runtime.Skia.WebAssembly.Browser/Devices/Input/BrowserKeyboardInputSource.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ private static byte OnNativeKeyboardEvent(
4242

4343
// Ensure that the async context is set properly, since we're raising
4444
// events from outside the dispatcher.
45-
using var syncContextScope = NativeDispatcher.Main.GetSynchronizationContext(NativeDispatcherPriority.Normal).Apply();
45+
using var syncContextScope = NativeDispatcher.Main.SynchronizationContext.Apply();
4646

4747
var args = new KeyEventArgs(
4848
"keyboard",

src/Uno.UI.Runtime.Skia.WebAssembly.Browser/Devices/Input/BrowserPointerInputSource.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ private static int OnNativeEvent(
8080

8181
// Ensure that the async context is set properly, since we're raising
8282
// events from outside the dispatcher.
83-
using var syncContextScope = NativeDispatcher.Main.GetSynchronizationContext(NativeDispatcherPriority.Normal).Apply();
83+
using var syncContextScope = NativeDispatcher.Main.SynchronizationContext.Apply();
8484

8585
var that = (BrowserPointerInputSource)inputSource;
8686
var evt = (HtmlPointerEvent)@event;

src/Uno.UI.Runtime.Skia.Wpf/Input/WpfCorePointerInputSource.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
using Windows.System;
1818
using Windows.UI.Core;
1919
using Windows.UI.Input;
20+
using Uno.UI.Dispatching;
2021
using Uno.UI.Runtime.Skia.Wpf;
2122
using Uno.UI.Runtime.Skia.Wpf.Hosting;
2223
using Uno.UI.Runtime.Skia.Wpf.UI.Controls;
@@ -140,10 +141,7 @@ private void HostOnMouseEvent(InputEventArgs args, TypedEventHandler<object, Poi
140141
try
141142
{
142143
// Make sure WPF doesn't override our own SynchronizationContext.
143-
if (Microsoft.UI.Xaml.Application.ApplicationSynchronizationContext is { } syncContext)
144-
{
145-
SynchronizationContext.SetSynchronizationContext(syncContext);
146-
}
144+
SynchronizationContext.SetSynchronizationContext(NativeDispatcher.Main.SynchronizationContext);
147145

148146
var eventArgs = BuildPointerArgs(args, isReleaseOrCancel);
149147
ev?.Invoke(this, eventArgs);

src/Uno.UI.RuntimeTests/Tests/Windows_System/Given_DispatcherQueue.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Threading.Tasks;
66
using Windows.System;
77
using Microsoft.VisualStudio.TestTools.UnitTesting;
8+
using Uno.UI.RuntimeTests.Helpers;
89

910
namespace Uno.UI.RuntimeTests.Tests.Windows_System
1011
{
@@ -26,5 +27,21 @@ public void When_GetForCurrentThreadFromBackgroundThread()
2627
Assert.IsNull(DispatcherQueue.GetForCurrentThread());
2728
}
2829
#endif
30+
31+
[TestMethod]
32+
[RunsOnUIThread]
33+
public async Task When_NativeDispatcherSynchronizationContext_Continuation_Scheduling()
34+
{
35+
var list = new List<int>();
36+
DispatcherQueue.GetForCurrentThread().TryEnqueue(DispatcherQueuePriority.High, async () =>
37+
{
38+
list.Add(1);
39+
await Task.Yield();
40+
list.Add(2);
41+
});
42+
DispatcherQueue.GetForCurrentThread().TryEnqueue(DispatcherQueuePriority.Normal, () => list.Add(3));
43+
await UITestHelper.WaitForIdle();
44+
CollectionAssert.AreEqual(new[] { 1, 3, 2 }, list);
45+
}
2946
}
3047
}

src/Uno.UI/Runtime/BrowserPointerInputSource.wasm.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ private static int OnNativeEvent(
102102

103103
// Ensure that the async context is set properly, since we're raising
104104
// events from outside the dispatcher.
105-
using var syncContextScope = NativeDispatcher.Main.GetSynchronizationContext(NativeDispatcherPriority.Normal).Apply();
105+
using var syncContextScope = NativeDispatcher.Main.SynchronizationContext.Apply();
106106

107107
var that = (BrowserPointerInputSource)inputSource;
108108
var evt = (HtmlPointerEvent)@event;

src/Uno.UI/UI/Xaml/Application.skia.cs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,6 @@ private void OnInvalidateRender(object? compositionTarget)
165165

166166
internal ISkiaApplicationHost? Host { get; set; }
167167

168-
internal static SynchronizationContext ApplicationSynchronizationContext { get; private set; }
169-
170168
private void SetCurrentLanguage()
171169
{
172170
if (CultureInfo.CurrentUICulture.IetfLanguageTag == "" &&
@@ -203,9 +201,7 @@ static partial void StartPartial(ApplicationInitializationCallback callback)
203201
{
204202
_startInvoked = true;
205203

206-
SynchronizationContext.SetSynchronizationContext(
207-
ApplicationSynchronizationContext = new NativeDispatcherSynchronizationContext(NativeDispatcher.Main, NativeDispatcherPriority.Normal)
208-
);
204+
SynchronizationContext.SetSynchronizationContext(NativeDispatcher.Main.SynchronizationContext);
209205

210206
callback(new ApplicationInitializationCallbackParams());
211207

src/Uno.UI/UI/Xaml/Application.wasm.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,7 @@ static async partial void StartPartial(ApplicationInitializationCallback callbac
8888
{
8989
_startInvoked = true;
9090

91-
SynchronizationContext.SetSynchronizationContext(
92-
new NativeDispatcherSynchronizationContext(NativeDispatcher.Main, NativeDispatcherPriority.Normal)
93-
);
91+
SynchronizationContext.SetSynchronizationContext(NativeDispatcher.Main.SynchronizationContext);
9492

9593
await WindowManagerInterop.InitAsync();
9694

src/Uno.UI/UI/Xaml/UIElement.EventRegistration.wasm.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ private HtmlEventDispatchResult InternalInnerDispatchEvent(EventArgs eventArgs,
252252
{
253253
// Ensure that the async context is set properly, since we're raising
254254
// events from outside the dispatcher.
255-
using var syncContextScope = NativeDispatcher.Main.GetSynchronizationContext(NativeDispatcherPriority.Normal).Apply();
255+
using var syncContextScope = NativeDispatcher.Main.SynchronizationContext.Apply();
256256

257257
if (_eventHandlers.TryGetValue((n, onCapturePhase), out var registration))
258258
{

0 commit comments

Comments
 (0)