Browse Source

Make Dispatcher.Yield use the current dispatcher (#20956)

pull/20549/merge
Julien Lebosquain 4 days ago
committed by GitHub
parent
commit
3068850405
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 5
      src/Avalonia.Base/Threading/Dispatcher.Invoke.cs
  2. 75
      tests/Avalonia.Base.UnitTests/DispatcherTests.cs

5
src/Avalonia.Base/Threading/Dispatcher.Invoke.cs

@ -737,9 +737,6 @@ public partial class Dispatcher
/// </exception> /// </exception>
public static DispatcherPriorityAwaitable Yield(DispatcherPriority priority) public static DispatcherPriorityAwaitable Yield(DispatcherPriority priority)
{ {
// TODO12: Update to use Dispatcher.CurrentDispatcher once multi-dispatcher support is merged return CurrentDispatcher.Resume(priority);
var current = UIThread;
current.VerifyAccess();
return UIThread.Resume(priority);
} }
} }

75
tests/Avalonia.Base.UnitTests/DispatcherTests.cs

@ -512,76 +512,59 @@ public partial class DispatcherTests
[Fact] [Fact]
public async Task DispatcherResumeContinuesOnUIThread() public async Task DispatcherResumeContinuesOnCurrentThread()
{ {
using var services = new DispatcherServices(new SimpleControlledDispatcherImpl()); using var services = new DispatcherServices(new SimpleControlledDispatcherImpl());
var tokenSource = new CancellationTokenSource(); var tokenSource = new CancellationTokenSource();
var workload = Dispatcher.UIThread.InvokeAsync( var dispatcher = Dispatcher.CurrentDispatcher;
var workload = dispatcher.InvokeAsync(
async () => async () =>
{ {
Assert.True(Dispatcher.UIThread.CheckAccess()); Assert.True(dispatcher.CheckAccess());
await Task.Delay(1).ConfigureAwait(false); await Task.Delay(1).ConfigureAwait(false);
Assert.False(Dispatcher.UIThread.CheckAccess()); Assert.False(dispatcher.CheckAccess());
await Dispatcher.UIThread.Resume(); await dispatcher.Resume();
Assert.True(Dispatcher.UIThread.CheckAccess()); Assert.True(dispatcher.CheckAccess());
tokenSource.Cancel(); tokenSource.Cancel();
}); });
Dispatcher.UIThread.MainLoop(tokenSource.Token); dispatcher.MainLoop(tokenSource.Token);
} }
[Fact] [Fact]
public async Task DispatcherYieldContinuesOnUIThread() public async Task DispatcherYieldContinuesOnCurrentThread()
{ {
using var services = new DispatcherServices(new SimpleControlledDispatcherImpl()); using var services = new DispatcherServices(new SimpleControlledDispatcherImpl());
var tokenSource = new CancellationTokenSource(); var tokenSource = new CancellationTokenSource();
var workload = Dispatcher.UIThread.InvokeAsync( var dispatcher = Dispatcher.CurrentDispatcher;
async () =>
{
Assert.True(Dispatcher.UIThread.CheckAccess());
await Dispatcher.Yield();
Assert.True(Dispatcher.UIThread.CheckAccess());
tokenSource.Cancel();
});
Dispatcher.UIThread.MainLoop(tokenSource.Token);
}
[Fact]
public async Task DispatcherYieldThrowsOnNonUIThread()
{
using var services = new DispatcherServices(new SimpleControlledDispatcherImpl());
var tokenSource = new CancellationTokenSource(); var workload = dispatcher.InvokeAsync(
var workload = Dispatcher.UIThread.InvokeAsync(
async () => async () =>
{ {
Assert.True(Dispatcher.UIThread.CheckAccess()); Assert.True(dispatcher.CheckAccess());
await Task.Delay(1).ConfigureAwait(false); await Dispatcher.Yield();
Assert.False(Dispatcher.UIThread.CheckAccess()); Assert.True(dispatcher.CheckAccess());
await Assert.ThrowsAsync<InvalidOperationException>(async () => await Dispatcher.Yield());
tokenSource.Cancel(); tokenSource.Cancel();
}); });
Dispatcher.UIThread.MainLoop(tokenSource.Token); dispatcher.MainLoop(tokenSource.Token);
} }
[Fact] [Fact]
public async Task AwaitWithPriorityRunsOnUIThread() public async Task AwaitWithPriorityRunsOnCurrentThread()
{ {
static async Task<int> Workload() static async Task<int> Workload(Dispatcher dispatcher)
{ {
await Task.Delay(1).ConfigureAwait(false); await Task.Delay(1).ConfigureAwait(false);
Assert.False(Dispatcher.UIThread.CheckAccess()); Assert.False(dispatcher.CheckAccess());
return Thread.CurrentThread.ManagedThreadId; return Thread.CurrentThread.ManagedThreadId;
} }
@ -589,25 +572,27 @@ public partial class DispatcherTests
using var services = new DispatcherServices(new SimpleControlledDispatcherImpl()); using var services = new DispatcherServices(new SimpleControlledDispatcherImpl());
var tokenSource = new CancellationTokenSource(); var tokenSource = new CancellationTokenSource();
var workload = Dispatcher.UIThread.InvokeAsync( var dispatcher = Dispatcher.CurrentDispatcher;
var workload = dispatcher.InvokeAsync(
async () => async () =>
{ {
Assert.True(Dispatcher.UIThread.CheckAccess()); Assert.True(dispatcher.CheckAccess());
Task taskWithoutResult = Workload(); Task taskWithoutResult = Workload(dispatcher);
await Dispatcher.UIThread.AwaitWithPriority(taskWithoutResult, DispatcherPriority.Default); await dispatcher.AwaitWithPriority(taskWithoutResult, DispatcherPriority.Default);
Assert.True(Dispatcher.UIThread.CheckAccess()); Assert.True(dispatcher.CheckAccess());
Task<int> taskWithResult = Workload(); Task<int> taskWithResult = Workload(dispatcher);
await Dispatcher.UIThread.AwaitWithPriority(taskWithResult, DispatcherPriority.Default); await dispatcher.AwaitWithPriority(taskWithResult, DispatcherPriority.Default);
Assert.True(Dispatcher.UIThread.CheckAccess()); Assert.True(dispatcher.CheckAccess());
tokenSource.Cancel(); tokenSource.Cancel();
}); });
Dispatcher.UIThread.MainLoop(tokenSource.Token); dispatcher.MainLoop(tokenSource.Token);
} }
private class AsyncLocalTestClass private class AsyncLocalTestClass

Loading…
Cancel
Save