A Microsoft open-source framework for building native device applications spanning mobile, tablet, and desktop.
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:
- Do not call
ShowPopupAsyncinsideTask.Run. - Do not use
task.Wait()or.Resulton async UI operations; alwaysawaitthem. - Ensure
ShowPopupAsyncis 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: