Skip to content

Commit c13dfe0

Browse files
authored
Add platform-specific main thread schedulers for MAUI (#4212)
<!-- Please be sure to read the [Contribute](https://github.com/reactiveui/reactiveui#contribute) section of the README --> **What kind of change does this PR introduce?** <!-- Bug fix, feature, docs update, ... --> Fixes #4185 **What is the current behavior?** <!-- You can also link to an open issue here. --> #4185 **What is the new behavior?** <!-- If this is a feature change --> Introduces AndroidMainThreadScheduler and AppleMainThreadScheduler properties for platform-specific main thread scheduling. Updates WithMauiScheduler to use the appropriate scheduler based on the target platform, improving UI thread handling for Android, iOS, macOS, and Mac Catalyst. **What might this PR break?** Resolves a threading issue with Maui **Please check if the PR fulfills these requirements** - [ ] Tests for the changes have been added (for bug fixes / features) - [ ] Docs have been added / updated (for bug fixes / features) **Other information**:
1 parent da99d4a commit c13dfe0

File tree

2 files changed

+49
-4
lines changed

2 files changed

+49
-4
lines changed

src/ReactiveUI.Maui/Builder/MauiReactiveUIBuilderExtensions.cs

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,43 @@ namespace ReactiveUI.Builder;
1313
public static class MauiReactiveUIBuilderExtensions
1414
{
1515
/// <summary>
16-
/// Gets the maui main thread scheduler.
16+
/// Gets the MAUI main thread scheduler.
1717
/// </summary>
1818
/// <value>
19-
/// The maui main thread scheduler.
19+
/// The MAUI main thread scheduler.
2020
/// </value>
2121
public static IScheduler MauiMainThreadScheduler { get; } = DefaultScheduler.Instance;
2222

23+
#if WINUI_TARGET
24+
/// <summary>
25+
/// Gets a scheduler that schedules work on the WinUI or .NET MAUI main UI thread, if available.
26+
/// </summary>
27+
/// <remarks>Use this scheduler to ensure that actions are executed on the main thread in WinUI or .NET
28+
/// MAUI applications. This is useful for updating UI elements or performing operations that require main thread
29+
/// access. If called from a non-main thread, scheduled actions will be marshaled to the main UI thread.</remarks>
30+
public static IScheduler WinUIMauiMainThreadScheduler { get; } = new WaitForDispatcherScheduler(static () => DispatcherQueueScheduler.Current);
31+
#endif
32+
33+
#if ANDROID
34+
/// <summary>
35+
/// Gets the scheduler that schedules work on the Android main (UI) thread.
36+
/// </summary>
37+
/// <remarks>Use this scheduler to execute actions that must run on the Android UI thread, such as
38+
/// updating user interface elements from background operations. This property is only available on Android
39+
/// platforms.</remarks>
40+
public static IScheduler AndroidMainThreadScheduler { get; } = HandlerScheduler.MainThreadScheduler;
41+
#endif
42+
43+
#if MACCATALYST || IOS || MACOS || TVOS
44+
/// <summary>
45+
/// Gets the scheduler that schedules work on the Apple main (UI) thread.
46+
/// </summary>
47+
/// <remarks>Use this scheduler to execute actions that must run on the main UI thread of Apple platforms,
48+
/// such as updating user interface elements from background operations. This property is available on macOS, iOS,
49+
/// and Mac Catalyst platforms.</remarks>
50+
public static IScheduler AppleMainThreadScheduler { get; } = new WaitForDispatcherScheduler(static () => new NSRunloopScheduler());
51+
#endif
52+
2353
/// <summary>
2454
/// Configures ReactiveUI for MAUI platform with appropriate schedulers.
2555
/// </summary>
@@ -43,7 +73,7 @@ public static IReactiveUIBuilder WithMaui(this IReactiveUIBuilder builder, IDisp
4373
}
4474

4575
/// <summary>
46-
/// Withes the maui scheduler.
76+
/// Adds the MAUI scheduler.
4777
/// </summary>
4878
/// <param name="builder">The builder.</param>
4979
/// <returns>The builder instance for chaining.</returns>
@@ -54,6 +84,21 @@ public static IReactiveUIBuilder WithMauiScheduler(this IReactiveUIBuilder build
5484
throw new ArgumentNullException(nameof(builder));
5585
}
5686

87+
builder.WithTaskPoolScheduler(TaskPoolScheduler.Default);
88+
89+
if (ModeDetector.InUnitTestRunner())
90+
{
91+
return builder.WithMainThreadScheduler(RxApp.UnitTestMainThreadScheduler);
92+
}
93+
94+
#if ANDROID
95+
return builder.WithMainThreadScheduler(AndroidMainThreadScheduler);
96+
#elif MACCATALYST || IOS || MACOS || TVOS
97+
return builder.WithMainThreadScheduler(AppleMainThreadScheduler);
98+
#elif WINUI_TARGET
99+
return builder.WithMainThreadScheduler(WinUIMauiMainThreadScheduler);
100+
#else
57101
return builder.WithMainThreadScheduler(MauiMainThreadScheduler);
102+
#endif
58103
}
59104
}

src/ReactiveUI/RxApp.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ public static ISuspensionHost SuspensionHost
238238
}
239239
}
240240

241-
private static IScheduler UnitTestMainThreadScheduler
241+
internal static IScheduler UnitTestMainThreadScheduler
242242
{
243243
get => _unitTestMainThreadScheduler ??= CurrentThreadScheduler.Instance;
244244

0 commit comments

Comments
 (0)