-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Expose DispatcherExtensions so it could be used outside of Maui as well #30488
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
Conversation
|
/azp run |
|
Azure Pipelines successfully started running 3 pipeline(s). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR exposes new DispatcherExtensions methods so they can be used outside of .NET MAUI and updates the Public API accordingly.
- Adds
DispatchIfRequiredand multipleDispatchIfRequiredAsyncoverloads toDispatcherExtensions - Updates unit tests to cover all new extension overloads
- Removes duplicate dispatcher helpers in
Controlsand adds necessary using directives
Reviewed Changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| src/Core/src/Dispatching/DispatcherExtensions.cs | Added new DispatchIfRequired and various DispatchIfRequiredAsync extension methods |
| src/Core/tests/UnitTests/Dispatching/DispatcherTests.cs | Added 14 new facts to verify each overload of the new extension methods |
| src/Core/src/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt | Registered the new extension methods in the Public API |
| src/Core/src/PublicAPI/netstandard/PublicAPI.Unshipped.txt | Registered the new extension methods in the Public API |
| src/Core/src/PublicAPI/net/PublicAPI.Unshipped.txt | Registered the new extension methods in the Public API |
| src/Core/src/PublicAPI/net-windows/PublicAPI.Unshipped.txt | Registered the new extension methods in the Public API |
| src/Core/src/PublicAPI/net-tizen/PublicAPI.Unshipped.txt | Registered the new extension methods in the Public API |
| src/Core/src/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt | Registered the new extension methods in the Public API |
| src/Core/src/PublicAPI/net-ios/PublicAPI.Unshipped.txt | Registered the new extension methods in the Public API |
| src/Core/src/PublicAPI/net-android/PublicAPI.Unshipped.txt | Registered the new extension methods in the Public API |
| src/Controls/src/Core/Handlers/Items/Android/ItemsSources/ObservableItemsSource.cs | Added using Microsoft.Maui.Dispatching; to use shared dispatcher extensions |
| src/Controls/src/Core/Handlers/Items/Android/ItemsSources/ObservableGroupedSource.cs | Added using Microsoft.Maui.Dispatching; to use shared dispatcher extensions |
| src/Controls/src/Core/DispatcherExtensions.cs | Removed local DispatchIfRequired* implementations in favor of the shared ones in Core |
| src/Controls/src/Core/BindingExpression.cs | Added using Microsoft.Maui.Dispatching; |
| src/Controls/src/Core/AppThemeBinding.cs | Added using Microsoft.Maui.Dispatching; |
Comments suppressed due to low confidence (4)
src/Core/src/Dispatching/DispatcherExtensions.cs:97
- New public extension methods require corresponding updates to the official documentation (under /docs) to describe DispatchIfRequired and its overloads.
public static void DispatchIfRequired(this IDispatcher dispatcher, Action action)
src/Core/src/Dispatching/DispatcherExtensions.cs:112
- Fill in the
<param>and<returns>XML comments for the DispatchIfRequiredAsync overloads to clearly document parameters and return values.
/// <param name="dispatcher"></param>
src/Controls/src/Core/BindingExpression.cs:13
- [nitpick] This using directive appears unused in this file; consider removing it to keep imports clean.
using Microsoft.Maui.Dispatching;
src/Controls/src/Core/AppThemeBinding.cs:6
- [nitpick] This using directive appears unused in this file; consider removing it to keep imports clean.
using Microsoft.Maui.Dispatching;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are some build errors:
C:\a\_work\1\s\src\Controls\src\Core\Platform\Windows\CollectionView\GroupedItemTemplateCollection.cs(83,26): error CS1061: 'IDispatcher' does not contain a definition for 'DispatchIfRequired' and no accessible extension method 'DispatchIfRequired' accepting a first argument of type 'IDispatcher' could be found (are you missing a using directive or an assembly reference?) [C:\a\_work\1\s\src\Controls\src\Core\Controls.Core.csproj::TargetFramework=net10.0-windows10.0.19041.0]
C:\a\_work\1\s\src\Controls\src\Core\Platform\Windows\CollectionView\ObservableItemTemplateCollection.cs(146,26): error CS1061: 'IDispatcher' does not contain a definition for 'DispatchIfRequired' and no accessible extension method 'DispatchIfRequired' accepting a first argument of type 'IDispatcher' could be found (are you missing a using directive or an assembly reference?) [C:\a\_work\1\s\src\Controls\src\Core\Controls.Core.csproj::TargetFramework=net10.0-windows10.0.19041.0]
C:\Users\cloudtest\.nuget\packages\microsoft.windowsappsdk\1.7.250606001\buildTransitive\Microsoft.UI.Xaml.Markup.Compiler.interop.targets(845,9): error MSB3073: The command ""C:\Users\cloudtest\.nuget\packages\microsoft.windowsappsdk\1.7.250606001\buildTransitive\..\tools\net6.0\..\net472\XamlCompiler.exe" "C:\a\_work\1\s\artifacts\obj\Controls.Core\Release\net10.0-windows10.0.19041.0\\input.json" "C:\a\_work\1\s\artifacts\obj\Controls.Core\Release\net10.0-windows10.0.19041.0\\output.json"" exited with code 1. [C:\a\_work\1\s\src\Controls\src\Core\Controls.Core.csproj::TargetFramework=net10.0-windows10.0.19041.0]
C:\a\_work\1\s\src\Compatibility\Core\src\iOS\VisualElementTracker.cs(347,21): error CS1061: 'IDispatcher' does not contain a definition for 'DispatchIfRequired' and no accessible extension method 'DispatchIfRequired' accepting a first argument of type 'IDispatcher' could be found (are you missing a using directive or an assembly reference?) [C:\a\_work\1\s\src\Compatibility\Core\src\Compatibility.csproj::TargetFramework=net10.0-ios18.5]
C:\a\_work\1\s\src\Compatibility\Core\src\iOS\VisualElementTracker.cs(347,21): error CS1061: 'IDispatcher' does not contain a definition for 'DispatchIfRequired' and no accessible extension method 'DispatchIfRequired' accepting a first argument of type 'IDispatcher' could be found (are you missing a using directive or an assembly reference?) [C:\a\_work\1\s\src\Compatibility\Core\src\Compatibility.csproj::TargetFramework=net10.0-maccatalyst18.5]
C:\a\_work\1\s\src\Controls\src\Core\Platform\Windows\CollectionView\ObservableItemTemplateCollection.cs(146,26): error CS1061: 'IDispatcher' does not contain a definition for 'DispatchIfRequired' and no accessible extension method 'DispatchIfRequired' accepting a first argument of type 'IDispatcher' could be found (are you missing a using directive or an assembly reference?) [C:\a\_work\1\s\src\Controls\src\Core\Controls.Core.csproj::TargetFramework=net10.0-windows10.0.20348.0]
C:\a\_work\1\s\src\Controls\src\Core\Platform\Windows\CollectionView\GroupedItemTemplateCollection.cs(83,26): error CS1061: 'IDispatcher' does not contain a definition for 'DispatchIfRequired' and no accessible extension method 'DispatchIfRequired' accepting a first argument of type 'IDispatcher' could be found (are you missing a using directive or an assembly reference?) [C:\a\_work\1\s\src\Controls\src\Core\Controls.Core.csproj::TargetFramework=net10.0-windows10.0.20348.0]
C:\Users\cloudtest\.nuget\packages\microsoft.windowsappsdk\1.7.250606001\buildTransitive\Microsoft.UI.Xaml.Markup.Compiler.interop.targets(845,9): error MSB3073: The command ""C:\Users\cloudtest\.nuget\packages\microsoft.windowsappsdk\1.7.250606001\buildTransitive\..\tools\net6.0\..\net472\XamlCompiler.exe" "C:\a\_work\1\s\artifacts\obj\Controls.Core\Release\net10.0-windows10.0.20348.0\\input.json" "C:\a\_work\1\s\artifacts\obj\Controls.Core\Release\net10.0-windows10.0.20348.0\\output.json"" exited with code 1. [C:\a\_work\1\s\src\Controls\src\Core\Controls.Core.csproj::TargetFramework=net10.0-windows10.0.20348.0]
C:\a\_work\1\s\src\Compatibility\Core\src\Android\CollectionView\ObservableGroupedSource.cs(235,35): error CS1061: 'IDispatcher' does not contain a definition for 'DispatchIfRequired' and no accessible extension method 'DispatchIfRequired' accepting a first argument of type 'IDispatcher' could be found (are you missing a using directive or an assembly reference?) [C:\a\_work\1\s\src\Compatibility\Core\src\Compatibility.csproj::TargetFramework=net10.0-android36.0]
C:\a\_work\1\s\src\Compatibility\Core\src\Android\CollectionView\ObservableItemsSource.cs(94,26): error CS1061: 'IDispatcher' does not contain a definition for 'DispatchIfRequired' and no accessible extension method 'DispatchIfRequired' accepting a first argument of type 'IDispatcher' could be found (are you missing a using directive or an assembly reference?) [C:\a\_work\1\s\src\Compatibility\Core\src\Compatibility.csproj::TargetFramework=net10.0-android36.0]
10 Error(s)
Could you review it?
@jsuarezruiz I’ve resolved the build errors. Please let me know if any further changes are required. |
|
/azp run |
|
Azure Pipelines successfully started running 3 pipeline(s). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tests are failing
02435a8 to
2af8944
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rebase to fix published
2af8944 to
b5856bc
Compare
@PureWeen Rebased the branch and resolved the conflicts. |
|
/azp run |
|
Azure Pipelines successfully started running 3 pipeline(s). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RADLE : warning : We recommend using a newer Android Gradle plugin to use compileSdk = 34 [/mnt/vss/_work/1/s/src/Core/src/Core.csproj::TargetFramework=net10.0-android36.0]
/mnt/vss/_work/1/s/src/Core/src/PublicAPI/net-android/PublicAPI.Unshipped.txt(201,1): error RS0025: The symbol 'static Microsoft.Maui.Dispatching.DispatcherExtensions.DispatchIfRequired(this Microsoft.Maui.Dispatching.IDispatcher! dispatcher, System.Action! action) -> void' appears more than once in the public API files (https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/PublicApiAnalyzers/PublicApiAnalyzers.Help.md) [/mnt/vss/_work/1/s/src/Core/src/Core.csproj::TargetFramework=net10.0-android36.0]
/mnt/vss/_work/1/s/src/Core/src/PublicAPI/net-android/PublicAPI.Unshipped.txt(202,1): error RS0025: The symbol 'static Microsoft.Maui.Dispatching.DispatcherExtensions.DispatchIfRequiredAsync(this Microsoft.Maui.Dispatching.IDispatcher! dispatcher, System.Action! action) -> System.Threading.Tasks.Task!' appears more than once in the public API files (https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/PublicApiAnalyzers/PublicApiAnalyzers.Help.md) [/mnt/vss/_work/1/s/src/Core/src/Core.csproj::TargetFramework=net10.0-android36.0]
/mnt/vss/_work/1/s/src/Core/src/PublicAPI/net-android/PublicAPI.Unshipped.txt(203,1): error RS0025: The symbol 'static Microsoft.Maui.Dispatching.DispatcherExtensions.DispatchIfRequiredAsync(this Microsoft.Maui.Dispatching.IDispatcher! dispatcher, System.Func<System.Threading.Tasks.Task!>! action) -> System.Threading.Tasks.Task!' appears more than once in the public API files (https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/PublicApiAnalyzers/PublicApiAnalyzers.Help.md) [/mnt/vss/_work/1/s/src/Core/src/Core.csproj::TargetFramework=net10.0-android36.0]
/mnt/vss/_work/1/s/src/Core/src/PublicAPI/net-android/PublicAPI.Unshipped.txt(204,1): error RS0025: The symbol 'static Microsoft.Maui.Dispatching.DispatcherExtensions.DispatchIfRequiredAsync(this Microsoft.Maui.Dispatching.IDispatcher! dispatcher, System.Func! func) -> System.Threading.Tasks.Task!' appears more than once in the public API files (https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/PublicApiAnalyzers/PublicApiAnalyzers.Help.md) [/mnt/vss/_work/1/s/src/Core/src/Core.csproj::TargetFramework=net10.0-android36.0]
/mnt/vss/_work/1/s/src/Core/src/PublicAPI/net-android/PublicAPI.Unshipped.txt(205,1): error RS0025: The symbol 'static Microsoft.Maui.Dispatching.DispatcherExtensions.DispatchIfRequiredAsync(this Microsoft.Maui.Dispatching.IDispatcher! dispatcher, System.Func<System.Threading.Tasks.Task!>! funcTask) -> System.Threading.Tasks.Task!' appears more than once in the public API files (https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/PublicApiAnalyzers/PublicApiAnalyzers.Help.md) [/mnt/vss/_work/1/s/src/Core/src/Core.csproj::TargetFramework=net10.0-android36.0]
Build FAILED.
GRADLE : warning : We recommend using a newer Android Gradle plugin to use compileSdk = 34 [/mnt/vss/_work/1/s/src/Core/src/Core.csproj::TargetFramework=net10.0-android36.0]
/mnt/vss/_work/1/s/src/Core/src/PublicAPI/net-android/PublicAPI.Unshipped.txt(201,1): error RS0025: The symbol 'static Microsoft.Maui.Dispatching.DispatcherExtensions.DispatchIfRequired(this Microsoft.Maui.Dispatching.IDispatcher! dispatcher, System.Action! action) -> void' appears more than once in the public API files (https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/PublicApiAnalyzers/PublicApiAnalyzers.Help.md) [/mnt/vss/_work/1/s/src/Core/src/Core.csproj::TargetFramework=net10.0-android36.0]
/mnt/vss/_work/1/s/src/Core/src/PublicAPI/net-android/PublicAPI.Unshipped.txt(202,1): error RS0025: The symbol 'static Microsoft.Maui.Dispatching.DispatcherExtensions.DispatchIfRequiredAsync(this Microsoft.Maui.Dispatching.IDispatcher! dispatcher, System.Action! action) -> System.Threading.Tasks.Task!' appears more than once in the public API files (https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/PublicApiAnalyzers/PublicApiAnalyzers.Help.md) [/mnt/vss/_work/1/s/src/Core/src/Core.csproj::TargetFramework=net10.0-android36.0]
/mnt/vss/_work/1/s/src/Core/src/PublicAPI/net-android/PublicAPI.Unshipped.txt(203,1): error RS0025: The symbol 'static Microsoft.Maui.Dispatching.DispatcherExtensions.DispatchIfRequiredAsync(this Microsoft.Maui.Dispatching.IDispatcher! dispatcher, System.Func<System.Threading.Tasks.Task!>! action) -> System.Threading.Tasks.Task!' appears more than once in the public API files (https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/PublicApiAnalyzers/PublicApiAnalyzers.Help.md) [/mnt/vss/_work/1/s/src/Core/src/Core.csproj::TargetFramework=net10.0-android36.0]
/mnt/vss/_work/1/s/src/Core/src/PublicAPI/net-android/PublicAPI.Unshipped.txt(204,1): error RS0025: The symbol 'static Microsoft.Maui.Dispatching.DispatcherExtensions.DispatchIfRequiredAsync(this Microsoft.Maui.Dispatching.IDispatcher! dispatcher, System.Func! func) -> System.Threading.Tasks.Task!' appears more than once in the public API files (https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/PublicApiAnalyzers/PublicApiAnalyzers.Help.md) [/mnt/vss/_work/1/s/src/Core/src/Core.csproj::TargetFramework=net10.0-android36.0]
/mnt/vss/_work/1/s/src/Core/src/PublicAPI/net-android/PublicAPI.Unshipped.txt(205,1): error RS0025: The symbol 'static Microsoft.Maui.Dispatching.DispatcherExtensions.DispatchIfRequiredAsync(this Microsoft.Maui.Dispatching.IDispatcher! dispatcher, System.Func<System.Threading.Tasks.Task!>! funcTask) -> System.Threading.Tasks.Task!' appears more than once in the public API files (https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/PublicApiAnalyzers/PublicApiAnalyzers.Help.md) [/mnt/vss/_work/1/s/src/Core/src/Core.csproj::TargetFramework=net10.0-android36.0]
1 Warning(s)
5 Error(s)
6872307 to
bb5571d
Compare
@PureWeen I have resolved the build errors and conflicts. |
|
/azp run |
|
Azure Pipelines successfully started running 3 pipeline(s). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- tests failing
@PureWeen The failed UI and device tests are passing locally. |
| if (dispatcher is null) | ||
| { | ||
| var currentThreadDispatcher = Dispatcher.GetForCurrentThread(); | ||
| if (currentThreadDispatcher?.IsDispatchRequired == true) | ||
| { | ||
| currentThreadDispatcher.Dispatch(action); | ||
| return; | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the reason for this additional bit of code? If dispatcher is null, then it probably should throw. You are asking it to run on the specified dispatcher, and it may give random results if there is no dispatcher.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mattleibow When the dispatcher is null, the method currently executes the action directly, which may not align with expectations in certain scenarios—such as in the PropertyChangeBindingsOccurThroughMainThread test, where InvokeOnMainThread is expected to be called when isOnBackgroundThread is true.
To address this, the additional logic uses Dispatcher.GetForCurrentThread() as a fallback to ensure the action is dispatched appropriately. This approach helps maintain thread-safety and ensures consistent behavior even when an explicit dispatcher reference is not available. It also allows mock dispatchers in test environments to be respected, avoiding unintended test failures or bypassed execution paths.
This change preserves expected behavior without altering the existing public contract and provides a safer fallback in cases where the dispatcher is not explicitly passed. Please let me know if you have any suggestions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think is fine is just an extra check, it will not throw and fallback to the previous way of just calling the action() if IsDispatchRequired on the new found dispatcher is false.
Note
Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!
Description of Change
Exposing the DispatcherExtensions so it could be used outside of Maui as well.
Issues Fixed
Fixes #29258