Share via

Show popup from a working thread Task

Giorgio Sfiligoi 616 Reputation points
2026-03-01T12:12:39.3433333+00:00

In my Android application (NET MAUI 10) I have code similar to the following:

    [RelayCommand]
    public async Task TaskPopup()
    {
        Debug.WriteLine("TaskPopup");
        Task task = Task.Run(async () =>
        {
            Debug.WriteLine("Some code before");

            await this.popupService.ShowPopupAsync<MyPopupViewModel>(Shell.Current);

            Debug.WriteLine("Some code after");
        });
        try
        {
            task.Wait();
        }
        catch(AggregateException ae)
        {
            Debug.WriteLine(ae.InnerException?.Message);
        }
    }

In Android Emulator the popup shows, but when I try to dismiss it, the program remains stuck.

In Output I read:

TaskPopup
Some code before
MyPopup ctor
'TestPopup.dll' (Mono: Default Domain): Loaded 'C:\Users\Coding\source\repos\TestMAUI 10\TestPopup\obj\Debug\net10.0-android\android\assets\x86_64\System.Drawing.Primitives.dll'. Symbol loading disabled by Include/Exclude setting.
Exception thrown: 'Android.Util.AndroidRuntimeException' in System.Private.CoreLib.dll
03-01 13:07:08.012 W/MaterialButton(24739): MaterialButton manages its own background to control elevation, shape, color and states. Consider using backgroundTint, shapeAppearance and other attributes where available. A custom background will ignore these attributes and you should consider handling interaction states such as pressed, focused and disabled
03-01 13:07:08.031 W/WindowOnBackDispatcher(24739): sendCancelIfRunning: isInProgress=false callback=androidx.activity.OnBackPressedDispatcher$Api34Impl$createOnBackAnimationCallback$1@7f7041d
03-01 13:07:08.133 D/InsetsController(24739): hide(ime(), fromIme=false)
03-01 13:07:08.134 I/ImeTracker(24739): com.companyname.testpopup:af2ed847: onCancelled at PHASE_CLIENT_ALREADY_HIDDEN
Exception thrown: 'Android.Util.AndroidRuntimeException' in System.Private.CoreLib.dll
Exception thrown: 'Android.Util.AndroidRuntimeException' in System.Private.CoreLib.dll
Exception thrown: 'Android.Util.AndroidRuntimeException' in System.Private.CoreLib.dll
Exception thrown: 'Android.Util.AndroidRuntimeException' in System.Private.CoreLib.dll
Exception thrown: 'System.AggregateException' in System.Private.CoreLib.dll
Only the original thread that created a view hierarchy can touch its views. Expected: main Calling: Thread-6

In Windows Machine the popup does not even show.

Is there any way to call a popup from a working thread?

Developer technologies | .NET | .NET MAUI
0 comments No comments
{count} votes

Answer accepted by question author
  1. Q&A Assist
    2026-03-01T12:12:51.7366667+00:00
    AI generated content. This question contains an answer created with AI from Q&A Assist. Learn more

    UI elements, including popups, must be created and interacted with on the main (UI) thread. The error

    Only the original thread that created a view hierarchy can touch its views. Expected: main Calling: Thread-6

    indicates that the popup is being shown from a background thread (Task.Run) and then blocked with task.Wait(), which deadlocks and violates Android’s UI-thread requirement.

    To show a popup from background work, keep the background work off the UI thread, but marshal the popup call back to the main thread and avoid blocking waits.

    A safe pattern is:

    [RelayCommand]
    public async Task TaskPopup()
    {
        Debug.WriteLine("TaskPopup");
    
        // Do background work first
        await Task.Run(() =>
        {
            Debug.WriteLine("Some code before");
            // long-running background work here
        });
    
        // Now switch to UI thread and show popup
        Debug.WriteLine("Showing popup");
        var result = await popupService.ShowPopupAsync<MyPopupViewModel>(Shell.Current);
    
        Debug.WriteLine("Some code after");
    }
    

    Key points:

    1. Do not call ShowPopupAsync inside Task.Run.
    2. Do not use task.Wait() or .Result on async UI operations; always await them.
    3. Ensure ShowPopupAsync is invoked from a UI-thread context (for example, directly from the command handler, which is already on the UI thread).

    If background work must continue while the popup is open, start that work in Task.Run, but keep the popup call itself on the UI thread and awaited.

    The same rule applies on Windows: UI must be updated only from the UI thread, so the above pattern also fixes the issue there.

    For completeness, ShowPopupAsync is designed to be awaited and returns an IPopupResult when the popup is closed or the cancellation token is canceled. It should always be used in an async flow rather than being wrapped in a blocking wait.


    References:

    0 comments No comments

1 additional answer

Sort by: Most helpful
  1. Nancy Vo (WICLOUD CORPORATION) 880 Reputation points Microsoft External Staff Moderator
    2026-03-06T06:56:47.3266667+00:00

    Hi @Giorgio Sfiligoi ,

    Thanks for reaching out.

    You can show a popup from a background thread, but you have to switch back to the main thread first. The problem is in .NET MAUI, only the main thread is allowed to touch the screen. Your code runs ShowPopupAsync on a background thread → crash or freeze.

    I recommend these solution:

    Replace this line:

    await this.popupService.ShowPopupAsync<MyPopupViewModel>(Shell.Current);
    

    with:

    await MainThread.InvokeOnMainThreadAsync(async () =>
    {
        await this.popupService.ShowPopupAsync<MyPopupViewModel>(Shell.Current);
    });
    

    Hope this helps. If you found my response helpful or informative, I would greatly appreciate it if you could follow this guidance provide feedback. Thank you.


Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.