AsyncRelayCommand causes InvalidOperation_HandleIsNotInitialized crashes in .NET 10 version of MAUI
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 32/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Cần làm rõ
- Mức độ hoạt động
- Ít trao đổi
- Công nghệ
- csharp
- Lĩnh vực
- mobile-dev
Hướng nghiên cứu
Bắt đầu với trình giám sát tác vụ thực thi của AsyncRelayCommand và đường dẫn NotifyCanExecuteChanged được hiển thị trong stack trace, sau đó kiểm tra cách nó đi đến MAUI Button.IsEnabled thông qua CommandElement.GetCanExecute và TypedBinding. So sánh hành vi của .NET 9 và .NET 10 trên Android và Windows; được xem là hoàn thành khi xác định được một cách tái hiện đáng tin cậy hoặc xác nhận được tương tác kích hoạt mà không xảy ra crash đã báo cáo.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Describe the bug
After upgrading MAUI from .NET 9 version to .NET 10 (specifically 10.0.51), random crashes are reported. I'm not able to reproduce it but the crash rate surged for both Android and Windows (I don't release for iOS/Mac).
There are 2 scenarios that causes the crash:
-
Using any AsyncRelayCommand that prevents concurrent execution (which is the default setting). When the command finishes, it runs NotifyCanExecuteChanged internally. That causes IsEnabled property to a Button that uses the command to be updated and that can randomly cause the app to crash with InvalidOperation_HandleIsNotInitialized. Workaround: I managed to mitigate the crashes by creating the commands with AsyncRelayCommandOptions.AllowConcurrentExecutions option and preventing concurrent execution manually in my code. It added a lot of boiler plate code so I don't like the solution but it definitelly helped.
-
** Calling NotifyCanExecuteChanged() in the code** can unfurtunatelly also crash the app. This is less frequent by the first case but it happends. My workaround was to create a helper method that calls NotifyCanExecuteChanged() on an AsyncRelayCommand but encloses the call in a try..catch block silently catching all exceptions and reporting them. Again, not a great solution, but necessary for .NET MAUI to keep the crash rate back on a .NET 9 level.
I'm not sure what was changed and if the problem is in MVVM toolkit or MAUI.
Example of the stack traces:
android.runtime.JavaProxyThrowable: [System.InvalidOperationException]: InvalidOperation_HandleIsNotInitialized
at System.WeakReference`1[[Microsoft.Maui.Controls.BindableObject, Microsoft.Maui.Controls, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null]].SetTarget + 0x29(Unknown Source:-1)
at Microsoft.Maui.Controls.Internals.TypedBinding`2[[System.String, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].ApplyToResolvedSource + 0x0(Unknown Source:-1)
at Microsoft.Maui.Controls.Internals.TypedBinding`2[[System.String, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].Apply + 0xa8(Unknown Source:-1)
at Microsoft.Maui.Controls.BindableObject.ForceBindingApply + 0x27(Unknown Source:-1)
at Microsoft.Maui.Controls.CommandElement.GetCanExecute + 0x43(Unknown Source:-1)
at Microsoft.Maui.Controls.Button.get_IsEnabledCore + 0x8(Unknown Source:-1)
at Microsoft.Maui.Controls.VisualElement.CoerceIsEnabledProperty + 0x16(Unknown Source:-1)
at Microsoft.Maui.Controls.BindableObject.SetValueCore + 0xf7(Unknown Source:-1)
at Microsoft.Maui.Controls.BindableObject.SetValue + 0x55(Unknown Source:-1)
at Microsoft.Maui.Controls.BindableObjectExtensions.RefreshPropertyValue + 0x45(Unknown Source:-1)
at Microsoft.Maui.Controls.VisualElement.RefreshIsEnabledProperty + 0x0(Unknown Source:-1)
at Microsoft.Maui.Controls.Button.Microsoft.Maui.Controls.Internals.ICommandElement.CanExecuteChanged + 0x0(Unknown Source:-1)
at Microsoft.Maui.Controls.WeakCommandSubscription+CommandCanExecuteSubscription.CanExecuteChanged + 0x2c(Unknown Source:-1)
at Unknown.Unknown(Unknown Source:-1)
at CommunityToolkit.Mvvm.Input.AsyncRelayCommand`1+<<set_ExecutionTask>g__MonitorTask|22_0>d[[System.String, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext + 0x111(Unknown Source:-1)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw + 0x11(Unknown Source:-1)
at System.Threading.Tasks.Task+<>c.<ThrowAsync>b__124_0 + 0x0(Unknown Source:-1)
at Android.App.SyncContext+<>c__DisplayClass2_0.<Post>b__0 + 0x0(Unknown Source:-1)
at Java.Lang.Thread+RunnableImplementor.Run + 0x8(Unknown Source:-1)
at Java.Lang.IRunnableInvoker.n_Run + 0x16(Unknown Source:-1)
at mono.java.lang.RunnableImplementor.n_run(RunnableImplementor.java:-2)
at mono.java.lang.RunnableImplementor.run(RunnableImplementor.java:21)
at android.os.Handler.handleCallback(Handler.java:995)
at android.os.Handler.dispatchMessage(Handler.java:103)
at android.os.Looper.loopOnce(Looper.java:273)
at android.os.Looper.loop(Looper.java:363)
at android.app.ActivityThread.main(ActivityThread.java:10060)
at java.lang.reflect.Method.invoke(Method.java:-2)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:632)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:975)
Regression
Not sure. It used to work in .NET 9 version of MAUI and started to crash aftter upgrading to .NET 10.
Steps to reproduce
I cannot reproduce it locally. The AppCenter reports that the app crashes sometimes after an hour if its usage, sometimes just in a few minutes. The crashes are random but too frequent to be ignored.
Expected behavior
No crashes as with the .NET 9 version of MAUI
Screenshots
No response
IDE and version
Other
IDE version
VS2026 (18.5.2)
Nuget packages
- CommunityToolkit.Common
- CommunityToolkit.Diagnostics
- CommunityToolkit.HighPerformance
- CommunityToolkit.Mvvm (aka MVVM Toolkit)
Nuget package version(s)
8.4.2
Additional context
No response
Help us help you
No, just wanted to report this
- Ngôn ngữ chính
- C#
- Star
- 3.8k
- Fork
- 403
- Chỉ số merge pull request
- Không có pull request nào được merge trong 30 ngày
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của CommunityToolkit/dotnet
-
RelayCommand<T>.CanExecute(null) returns false for value types without a predicateCó thể đã có người làm @apachezy đã nhận 87 ngày trước. Đang mởbug :bug:
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 84/100
CommunityToolkit/dotnet#1206 ·
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100
CommunityToolkit/dotnet#1186 ·
-
bug :bug:
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 68/100
CommunityToolkit/dotnet#648 ·
-
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 35/100
CommunityToolkit/dotnet#1217 ·
-
bug :bug:
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 68/100
CommunityToolkit/dotnet#1215 ·
Tất cả issue của CommunityToolkit/dotnet
Issue tương tự
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 64/100
joinrpg/joinrpg-net#5752 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug ux
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
CodeForFire/lagebuch#714 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
dimitar-radenkov/Pointframe#294 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
kind/feature-request
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
Altinn/altinn-correspondence#2154 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Batteries can't be swappedĐang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 61/100
Okabintaro/SubmersedVR#253 ·