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

[C# Markup] Command executes on a background thread #2618

Open
DevTKSS opened this issue Nov 1, 2024 · 1 comment
Open

[C# Markup] Command executes on a background thread #2618

DevTKSS opened this issue Nov 1, 2024 · 1 comment
Assignees
Labels
kind/bug Something isn't working project/csharp-markup triage/untriaged Indicates an issue requires triaging or verification.

Comments

@DevTKSS
Copy link

DevTKSS commented Nov 1, 2024

Current behavior

Not showing any ContentDialog created from MmainModel using xamlRootProvider thats xamlRoot was set while the Page Loaded Event
Same Behaviour if you try to do the call from a xaml Markup App > MainModel
place the in this case async void (see video in the uno reference to ContentDialog which uses the Click event) in the mainPage
xaml.cs codebehind and you will have no problem, so in my opinion its defintly a mvux issue from related to the ViewModel.

Exception Details:
System.InvalidOperationException
  HResult=0x80131509
  Nachricht = **The dependency property system should not be accessed from non UI thread.**
  Quelle = Uno.UI
  Stapelüberwachung:
   bei Microsoft.UI.Xaml.DependencyProperty.GetProperty(Type type, String name)
   bei Microsoft.UI.Xaml.DependencyObjectStore.GetLocalPropertyDetails(DependencyProperty property)
   bei Microsoft.UI.Xaml.DependencyObjectStore.OnParentPropertyChangedCallback(ManagedWeakReference sourceInstance, DependencyProperty parentProperty, Object newValue)
   bei Microsoft.UI.Xaml.DependencyObjectStore.CallChildCallback(DependencyObjectStore childStore, ManagedWeakReference instanceRef, DependencyProperty property, Object newValue)
   bei Microsoft.UI.Xaml.DependencyObjectStore.InvokeCallbacks(DependencyObject actualInstanceAlias, DependencyProperty property, DependencyPropertyDetails propertyDetails, Object previousValue, DependencyPropertyValuePrecedences previousPrecedence, Object newValue, DependencyPropertyValuePrecedences newPrecedence, Boolean bypassesPropagation)
   bei Microsoft.UI.Xaml.DependencyObjectStore.InnerSetValue(DependencyProperty property, Object value, DependencyPropertyValuePrecedences precedence, DependencyPropertyDetails propertyDetails, Boolean isPersistentResourceBinding)
   bei Microsoft.UI.Xaml.DependencyObjectStore.SetValue(DependencyProperty property, Object value)
   bei Microsoft.UI.Xaml.UIElement.SetValue(DependencyProperty dp, Object value)
   bei Microsoft.UI.Xaml.NameScope.SetNameScope(DependencyObject dependencyObject, INameScope value)
   bei Uno.Material.WinUI.__Resources._mergedpages_v2_44627d8de4433209f2b1934267892e44_mergedpages_v2RDSC13.Build(Object __ResourceOwner_1)
   bei Uno.Material.WinUI.GlobalStaticResources.ResourceDictionarySingleton__mergedpages_v2_44627d8de4433209f2b1934267892e44.<>c.<Get_54>b__33_1(Object __owner)
   bei Microsoft.UI.Xaml.FrameworkTemplate.Microsoft.UI.Xaml.IFrameworkTemplateInternal.LoadContent()
   bei Microsoft.UI.Xaml.FrameworkTemplatePool.DequeueTemplate(FrameworkTemplate template)
   bei Microsoft.UI.Xaml.FrameworkTemplate.LoadContentCached()
   bei Microsoft.UI.Xaml.Controls.Control.UpdateTemplate()
   bei Microsoft.UI.Xaml.Controls.Control.SetUpdateControlTemplate(Boolean forceUpdate)
   bei Microsoft.UI.Xaml.Controls.Control.ApplyTemplate()
   bei Microsoft.UI.Xaml.Controls.Control.EnsureTemplate()
   bei Microsoft.UI.Xaml.Controls.ContentDialog.<<ShowAsync>b__32_0>d.MoveNext()
   bei Windows.Foundation.AsyncOperation`1.<BuildTaskAsync>d__23.MoveNext()
   bei System.WindowsRuntimeSystemExtensions.<AsTaskCore>d__11`1.MoveNext()
   bei MyUnoApp.Presentation.MainModel.<ShowDialogAsync>d__12.MoveNext() in C:\Users\TKSSonja\Projects\MyUnoApp\MyUnoApp\Presentation\MainModel.cs: Zeile44

  Diese Ausnahme wurde ursprünglich von dieser Aufrufliste ausgelöst:
    [Externer Code]
    MyUnoApp.Presentation.MainModel.ShowDialogAsync() in MainModel.cs

Already checked:
xamlRoot is not null at this time

My calling code:

namespace MyUnoApp.Presentation;

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        Loaded += MainPage_Loaded;
        this.DataContext<MainViewModel>((page, vm) => page
            .NavigationCacheMode(NavigationCacheMode.Required)
            .Background(Theme.Brushes.Background.Default)
            .Content(new Grid()
                .SafeArea(SafeArea.InsetMask.VisibleBounds)
                .RowDefinitions("Auto,*")
                .Children(
                    new NavigationBar().Content(() => vm.Title),
                    new StackPanel()
                        .Grid(row: 1)
                        .HorizontalAlignment(HorizontalAlignment.Center)
                        .VerticalAlignment(VerticalAlignment.Center)
                        .Spacing(16)
                        .Children(
                            new TextBox()
                                .Text(x => x.Binding(() => vm.Name).Mode(BindingMode.TwoWay))
                                .PlaceholderText("Enter your name:"),
                            new Button()
                                .Content("Go to Second Page")
                                .AutomationProperties(automationId: "SecondPageButton")
                                .Command(() => vm.GoToSecond),
                            new Button()
                                .Name(out var GoRightButton)
                                .Content("Let's go right")
                                .AutomationProperties(automationId: "GoRightButton")
                                .Command(() =>vm.ShowDialogAsync) ///<- right here this Task is called
                                ),"

Task Code in MainModel:

public async Task ShowDialogAsync()
{
    try
    {
        ContentDialog dialog = new ContentDialog
        {
            Title = "Some Title",
            Content = "Some Content",
            PrimaryButtonText = "OK",
            XamlRoot = XamlRootService.GetXamlRoot(),
            DefaultButton = ContentDialogButton.Primary
        };

        ContentDialogResult result = await dialog.ShowAsync(); ///<- here it is throwing the exception you see above, but really resulting from the generated code in the MainViewModel
        await DialogResult.SetAsync(result switch
        {
            ContentDialogResult.Primary => "OK",
            _ => "Canceled",
        });
    }
    catch (Exception ex)
    {
        Console.WriteLine($"ShowDialogAsync got exception: {ex.Message}");
    }
}

DialogResult Property from Task content is in MainModel:

public IState<string> DialogResult => State<string>.Value(this, () => string.Empty);

Relevant things we discovered so far:
the SynchronisationContext is suddenly null if you call the task in the model! No reason for that found until now.
using

public async Task ShowDialogAsync()
{
    bool okClicked = false;

    var dialogActions = new DialogAction[]
    {
        new DialogAction("OK") { Action = () => okClicked = true },
        new DialogAction("Cancel"),
    };

    try
    {
        await _navigator.ShowMessageDialogAsync(this, "Some Title", "Some Content", buttons: dialogActions);
    }
    catch (Exception ex)
    {
    }

    if (okClicked)
    {
        await DialogResult.SetAsync("OK");
    }
    else
    {
        await DialogResult.SetAsync("Canceled");
    }
}

navigator attempt was written by @mikernet

Expected behavior

In my opinion that should be all fine and working, but somehow it is throwing this exception

How to reproduce it (as minimally and precisely as possible)

Repo link:
https://github.com/DevTKSS/MyUnoApp.git

Reproduce it this way:
run it in debug mode (tested targets so far: Andoid Emulator, Skia Desktop, Wasm)
set a breakpoint on the start of the task on the mainModel (can be done before starting debug)
click on the "Go Right" Button
if it breaks step throught with F11
at some point while stepping throught the await dialog.ShowAsync(); in the binding view model it will throw the exception because it thinks we are not in the ui thread, while we never left it.

Workaround

use xaml markup or mvvm

Works on UWP/WinUI

No

Environment

Uno.UI / Uno.UI.WebAssembly / Uno.UI.Skia, Uno.WinUI / Uno.WinUI.WebAssembly / Uno.WinUI.Skia

NuGet package version(s)

just the one uno-check installed by default

Affected platforms

WebAssembly, Android, Skia (WPF), Skia (GTK)

IDE

Visual Studio 2022

IDE version

Microsoft Visual Studio Community 2022 Version 17.11.5 VisualStudio.17.Release/17.11.5+35327.3 Microsoft .NET Framework Version 4.8.09032

Relevant plugins

No response

Anything else we need to know?

Possibly related to the mvux pattern thing, so maybe a mvux issue?
unoplatform/uno#18598 (comment)
Seems to not happen in mvvm

@DevTKSS DevTKSS added kind/bug Something isn't working triage/untriaged Indicates an issue requires triaging or verification. labels Nov 1, 2024
@mikernet
Copy link

mikernet commented Nov 1, 2024

For context, what I found while trying to assist with this issue was that a) MainModel appears to be created on a non-UI thread (SynchronizationContext.Current is null while its ctor runs) and b) ShowDialogAsync() also appears to be running on a non-UI thread, as it is also null there somehow.

@jeromelaban jeromelaban changed the title mvux application UI Thread is suddenly null while it shouldnt be that, not longer possible to call a contentDialog Task from MainModel althought xamlRoot is provided! [C# Markup] Command executes on a background thread Nov 4, 2024
@MartinZikmund MartinZikmund self-assigned this Nov 6, 2024
@jeromelaban jeromelaban transferred this issue from unoplatform/uno Nov 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/bug Something isn't working project/csharp-markup triage/untriaged Indicates an issue requires triaging or verification.
Projects
None yet
Development

No branches or pull requests

4 participants