From d84957f1f61c0126c86c439ed4a31821ce773735 Mon Sep 17 00:00:00 2001 From: Tom Edwards Date: Sun, 29 Mar 2026 20:48:06 +0200 Subject: [PATCH] Allow Dispatcher to be implicitly cast to TaskScheduler --- .../Threading/Dispatcher.TaskScheduler.cs | 31 +++++++++++++++++++ .../DispatcherTests.cs | 11 +++++++ 2 files changed, 42 insertions(+) create mode 100644 src/Avalonia.Base/Threading/Dispatcher.TaskScheduler.cs diff --git a/src/Avalonia.Base/Threading/Dispatcher.TaskScheduler.cs b/src/Avalonia.Base/Threading/Dispatcher.TaskScheduler.cs new file mode 100644 index 0000000000..d3bb0767c7 --- /dev/null +++ b/src/Avalonia.Base/Threading/Dispatcher.TaskScheduler.cs @@ -0,0 +1,31 @@ +using System.Threading; +using System.Threading.Tasks; + +namespace Avalonia.Threading; + +public partial class Dispatcher +{ + private TaskScheduler? _taskScheduler; + + public static implicit operator TaskScheduler(Dispatcher dispatcher) + { + lock (dispatcher.InstanceLock) + { + if (dispatcher._taskScheduler == null) + { + var prevContext = SynchronizationContext.Current; + SynchronizationContext.SetSynchronizationContext(dispatcher.GetContextWithPriority(DispatcherPriority.Default)); + try + { + dispatcher._taskScheduler = TaskScheduler.FromCurrentSynchronizationContext(); + } + finally + { + SynchronizationContext.SetSynchronizationContext(prevContext); + } + } + } + + return dispatcher._taskScheduler; + } +} diff --git a/tests/Avalonia.Base.UnitTests/DispatcherTests.cs b/tests/Avalonia.Base.UnitTests/DispatcherTests.cs index ffb94cc5d6..ece900e48a 100644 --- a/tests/Avalonia.Base.UnitTests/DispatcherTests.cs +++ b/tests/Avalonia.Base.UnitTests/DispatcherTests.cs @@ -764,4 +764,15 @@ public partial class DispatcherTests } } + [Fact] + public async Task Dispatcher_Can_Act_As_TaskScheduler() + { + var impl = new SimpleDispatcherImpl(); + Dispatcher.InitializeUIThreadDispatcher(impl); + Thread? continuationThread = null; + _ = Task.CompletedTask.ContinueWith(t => continuationThread = Thread.CurrentThread, Dispatcher.UIThread); + Assert.True(impl.AskedForSignal); + impl.ExecuteSignal(); + Assert.Equal(Dispatcher.UIThread.Thread, continuationThread); + } }