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

[BUG] Popup.CloseAsync causing a TargetInvocationException (UIThread) on iOS #2509

Open
2 tasks done
Sebastian1989101 opened this issue Feb 10, 2025 · 4 comments
Open
2 tasks done
Labels
bug Something isn't working unverified

Comments

@Sebastian1989101
Copy link

Is there an existing issue for this?

  • I have searched the existing issues

Did you read the "Reporting a bug" section on Contributing file?

Current Behavior

It seems like a Popup.CloseAsync() call can cause a UIThread issue when running on iOS. It runs fine on Android and if anything, I would assume this exception already when trying to display the Popup (as this is in the same async Task method in my case).

Expected Behavior

Popup.CloseAsync() makes sure it runs on the proper thread.

Steps To Reproduce

Not sure how much I would need to remove from my code to make this happen. This method is invoked from the constructor of the page:

    public async Task LoadDataWithKey(string? key)
    {
        LoadingPopup? loadingPopup = null;

        try
        {
            loadingPopup = new LoadingPopup { Message = AppResources.DefaultText_Loading };
            Shell.Current.ShowPopup(loadingPopup);

            var allCategories = await speedrunCategoryDatabaseRepository.GetAllAsync();
            Category = allCategories.First(c => c.Key == key)!;

            Entries = (await apiRepository.GetEntriesAsync(_category).ConfigureAwait(false))
                .Select(e => new SpeedrunEntryWrapperViewModel(e)).ToArray();
        }
        catch (Exception e)
        {
            logger.LogError(e, e.Message);
        }
        finally
        {
            if (loadingPopup != null)
            {
                await loadingPopup.CloseAsync();
                loadingPopup.DisposeIfDisposable();
            }
        }
    }

Link to public reproduction project repository

n/a

Environment

- .NET MAUI CommunityToolkit: 11.0.0
- OS: Windows 11 / iOS 16 as Debug Target
- .NET MAUI: 9

Anything else?

I know that I did not attached a reproduction project because I do not know yet how to isolate the issue so far that it's an issue. I just found out that on iOS I have to sent the Popup.CloseAsync() to the MainThread manually for my app to no longer crash with this exception.

@Sebastian1989101 Sebastian1989101 added bug Something isn't working unverified labels Feb 10, 2025
@VladislavAntonyuk
Copy link
Collaborator

There will be a major change soon with a new popup implementation, which should solve the issue

@pictos
Copy link
Member

pictos commented Feb 10, 2025

@Sebastian1989101 I see that you're using the ConfigureAwait(false) on your code... That will make all code bellow to be executed in any thread, so that probably is the root cause. I'm not sure why there's a difference between ios and android, but removing that ConfigureAwait should do the job... Or queue the CloseAsync method to run on UIThread, you can use the MainThread class for it

@Sebastian1989101
Copy link
Author

@pictos already sending it to the main thread. Was not an issue for me to get rid of the error, however I think a control should always self check to be on the proper thread (at least bindings and other controls from MAUI itself do this).

@pictos
Copy link
Member

pictos commented Feb 10, 2025

@Sebastian1989101, I somewhat disagree with that. If you try to force a control to update outside the UI thread, it will throw an exception. This is common sense in most UI frameworks, even on the native side. The app developer should take care of the threads.

To illustrate it better, if you do:

public MainPage() {
var lbl = new Label();
Content = lbl;
Loaded += async (_,__) => await Task.Run(() => lbl.Text = "banana");
} 

As a result, you will face this exception, proving my point that it is the responsibility of the app developer to ensure the code runs on the correct thread.
Image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working unverified
Projects
None yet
Development

No branches or pull requests

3 participants