Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Moving navigation to background thread #865

Merged
merged 8 commits into from
Oct 28, 2022
5 changes: 5 additions & 0 deletions src/Uno.Extensions.Core/IDispatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,9 @@ public interface IDispatcher
/// <param name="cancellation">An cancellation token to cancel the async operation.</param>
/// <returns>A ValueTask to asynchronously get the result of the operation.</returns>
ValueTask<TResult> ExecuteAsync<TResult>(AsyncFunc<TResult> func, CancellationToken cancellation);

/// <summary>
/// Gets a value that specifies whether the current execution context is on the UI thread.
/// </summary>
bool HasThreadAccess { get; }
}
2 changes: 1 addition & 1 deletion src/Uno.Extensions.Core/PlatformHelper.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace Uno.Extensions;

public class PlatformHelper
public static class PlatformHelper
{
private static bool _isNetCore;
private static bool _initialized;
Expand Down
12 changes: 11 additions & 1 deletion src/Uno.Extensions.Navigation.UI/Dispatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,15 @@ public Dispatcher(FrameworkElement element)

/// <inheritdoc />
public async ValueTask<TResult> ExecuteAsync<TResult>(AsyncFunc<TResult> func, CancellationToken cancellation)
=> await _dispatcher.ExecuteAsync(func, cancellation);
{
if (!PlatformHelper.IsWebAssembly && // Assume for web that we always call executeasync on dispatcher
nickrandolph marked this conversation as resolved.
Show resolved Hide resolved
HasThreadAccess)
{
return await func(cancellation);
}
return await _dispatcher.ExecuteAsync(func, cancellation);
}

/// <inheritdoc />
public bool HasThreadAccess => _dispatcher.HasThreadAccess;
}
9 changes: 9 additions & 0 deletions src/Uno.Extensions.Navigation.UI/Navigator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@ protected Navigator(
var regionUpdateId = RouteUpdater?.StartNavigation(Region) ?? Guid.Empty;
try
{

if (Dispatcher.HasThreadAccess &&
!request.InProgress)
{
request = request with { InProgress = true }; // Prevent multiple re-entrance where HasThreadAccess always returns true eg WASM
if (Logger.IsEnabled(LogLevel.Information)) Logger.LogInformationMessage($"Navigation started on UI thread, so moving to background thread");
return await Task.Run(() => NavigateAsync(request));
}

if (request.Source is null)
{
if (Logger.IsEnabled(LogLevel.Information)) Logger.LogInformationMessage($"Starting Navigation - Navigator: {this.GetType().Name} Request: {request.Route}");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,27 +99,28 @@ protected override async Task<bool> RegionCanNavigate(Route route, RouteInfo? ro
return path;
}

protected override Task PostNavigateAsync()
protected override async Task PostNavigateAsync()
{
if (Control is not null)
{
foreach (var child in Control.Children.OfType<FrameworkElement>())
await Dispatcher.ExecuteAsync(async cancellation =>
{
if(child == CurrentlyVisibleControl)
foreach (var child in Control.Children.OfType<FrameworkElement>())
{
child.Opacity = 1;
child.Visibility = Visibility.Visible;
}
else
{
child.Opacity = 0;
child.Visibility = Visibility.Collapsed;
if (child == CurrentlyVisibleControl)
{
child.Opacity = 1;
child.Visibility = Visibility.Visible;
}
else
{
child.Opacity = 0;
child.Visibility = Visibility.Collapsed;

}
}
}
});
}

return Task.CompletedTask;
}

private FrameworkElement? FindByPath(string? path)
Expand Down
2 changes: 2 additions & 0 deletions src/Uno.Extensions.Navigation/NavigationRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
public record NavigationRequest(object Sender, Route Route, CancellationToken? Cancellation = default, Type? Result = null, INavigator? Source = null)
#pragma warning restore SA1313 // Parameter names should begin with lower-case letter
{
internal bool InProgress { get; init; }

public override string ToString() => $"Request [Sender: {Sender.GetType().Name}, Route:{Route}, Result: {Result?.Name ?? "N/A"}]";

internal virtual IResponseNavigator? GetResponseNavigator(IResponseNavigatorFactory responseFactory, INavigator navigator) => default;
Expand Down
5 changes: 5 additions & 0 deletions testing/TestHarness/Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,9 @@
</Choose>

<Import Project="..\..\src\xamarinmac-workaround.targets" Condition="exists('..\..\src\xamarinmac-workaround.targets') and $(TargetFramework.ToLower().StartsWith('xamarin')) and $(TargetFramework.ToLower().Contains('mac'))" />

<!-- Uno.WinUI.MSAL references Uno.WinUI for windows10 tfm. This target
overrides the protection in uno.winui.targets that raises an error
that breaks build -->
<Target Name="_WinAppSDKNotSupported" BeforeTargets="BeforeBuild" />
</Project>
3 changes: 2 additions & 1 deletion testing/TestHarness/TestHarness-ui.slnf
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,16 @@
"..\\..\\src\\Uno.Extensions.Authentication.UI\\Uno.Extensions.Authentication.UI.csproj",
"..\\..\\src\\Uno.Extensions.Authentication\\Uno.Extensions.Authentication.csproj",
"..\\..\\src\\Uno.Extensions.Configuration\\Uno.Extensions.Configuration.csproj",
"..\\..\\src\\Uno.Extensions.Core.Generators\\Uno.Extensions.Core.Generators.csproj",
"..\\..\\src\\Uno.Extensions.Core\\Uno.Extensions.Core.csproj",
"..\\..\\src\\Uno.Extensions.Hosting.UI\\Uno.Extensions.Hosting.UWP.Skia.csproj",
"..\\..\\src\\Uno.Extensions.Hosting.UI\\Uno.Extensions.Hosting.UWP.Wasm.csproj",
"..\\..\\src\\Uno.Extensions.Hosting.UI\\Uno.Extensions.Hosting.UWP.csproj",
"..\\..\\src\\Uno.Extensions.Hosting\\Uno.Extensions.Hosting.csproj",
"..\\..\\src\\Uno.Extensions.Http.Refit\\Uno.Extensions.Http.Refit.csproj",
"..\\..\\src\\Uno.Extensions.Http\\Uno.Extensions.Http.csproj",
"..\\..\\src\\Uno.Extensions.Localization\\Uno.Extensions.Localization.csproj",
"..\\..\\src\\Uno.Extensions.Localization.UI\\Uno.Extensions.Localization.UI.csproj",
"..\\..\\src\\Uno.Extensions.Localization\\Uno.Extensions.Localization.csproj",
"..\\..\\src\\Uno.Extensions.Logging.Serilog\\Uno.Extensions.Logging.Serilog.csproj",
"..\\..\\src\\Uno.Extensions.Logging\\Uno.Extensions.Logging.UWP.Skia.csproj",
"..\\..\\src\\Uno.Extensions.Logging\\Uno.Extensions.Logging.UWP.Wasm.csproj",
Expand Down
3 changes: 2 additions & 1 deletion testing/TestHarness/TestHarness-winui.slnf
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,16 @@
"..\\..\\src\\Uno.Extensions.Authentication.UI\\Uno.Extensions.Authentication.WinUI.csproj",
"..\\..\\src\\Uno.Extensions.Authentication\\Uno.Extensions.Authentication.csproj",
"..\\..\\src\\Uno.Extensions.Configuration\\Uno.Extensions.Configuration.csproj",
"..\\..\\src\\Uno.Extensions.Core.Generators\\Uno.Extensions.Core.Generators.csproj",
"..\\..\\src\\Uno.Extensions.Core\\Uno.Extensions.Core.csproj",
"..\\..\\src\\Uno.Extensions.Hosting.UI\\Uno.Extensions.Hosting.WinUI.Skia.csproj",
"..\\..\\src\\Uno.Extensions.Hosting.UI\\Uno.Extensions.Hosting.WinUI.Wasm.csproj",
"..\\..\\src\\Uno.Extensions.Hosting.UI\\Uno.Extensions.Hosting.WinUI.csproj",
"..\\..\\src\\Uno.Extensions.Hosting\\Uno.Extensions.Hosting.csproj",
"..\\..\\src\\Uno.Extensions.Http.Refit\\Uno.Extensions.Http.Refit.csproj",
"..\\..\\src\\Uno.Extensions.Http\\Uno.Extensions.Http.csproj",
"..\\..\\src\\Uno.Extensions.Localization\\Uno.Extensions.Localization.csproj",
"..\\..\\src\\Uno.Extensions.Localization.UI\\Uno.Extensions.Localization.WinUI.csproj",
"..\\..\\src\\Uno.Extensions.Localization\\Uno.Extensions.Localization.csproj",
"..\\..\\src\\Uno.Extensions.Logging.Serilog\\Uno.Extensions.Logging.Serilog.csproj",
"..\\..\\src\\Uno.Extensions.Logging\\Uno.Extensions.Logging.WinUI.Skia.csproj",
"..\\..\\src\\Uno.Extensions.Logging\\Uno.Extensions.Logging.WinUI.Wasm.csproj",
Expand Down
2 changes: 1 addition & 1 deletion testing/TestHarness/TestHarness.UITest/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ namespace TestHarness.UITest;

public class Constants
{
public readonly static string WebAssemblyDefaultUri = "https://localhost:51571";
public readonly static string WebAssemblyDefaultUri = "https://localhost:64052";
public readonly static string iOSAppName = "uno.platform.extensions.demo";
public readonly static string AndroidAppName = "uno.platform.extensions.demo";
public readonly static string iOSDeviceNameOrId = "iPad Pro (12.9-inch) (4th generation)";
Expand Down