If you choose to use C# async/await, you must get on to the correct thread before calling any async method. Put a breakpoint on the start of the method in your question - before it calls BeginInvoke. Go up your call stack, till you get to a method that isn't declared async. That is the method that must do BeginInvokeOnMainThread, as a wrapper around all your async code.
Be sure to remove BeginInvokeOnMainThread from the code you showed - once you are inside async/await, that won't do what you want.
DISCLAIMER: It would be better to instead make a fundamental change somewhere else.
Why are you on a background thread, but require a UI call?
There are a variety of mechanisms for splitting your code into the UI portion and the background portion: you haven't fully done so, or you wouldn't be having this problem.
Perhaps you need a background task with a progress callback. That callback communicates with user as needed.
Or you need to have the background task's "completion" report to your main code that it cannot continue without user input, do the user input in that main code, then start another background task to finish the work.
Or earlier in your code, before beginning your background task, you needed to verify that you had all needed info from user, and communicate there.
If those aren't enough hints to head you in a workable direction, I recommend finding a more complete example of async/await used in an app, study what it does. If you still have this question, then add more detail to it.
That's the "pure" answer.
In practice, I have found it sometimes easier to throw in a BeginInvokeOnMainThread - and then write code without async/await.
G.Hakim made the essential observation:
DisplayAlert is a Task returning method ...
See Microsoft doc- Chaining Tasks by Using Continuation Tasks if you want to understand how to call DisplayAlert, then do something else afterwards.
Going down this road, I think you need to remove async and await from your method. You'll be doing the "asynchronous" calling yourself.
Instead of trying to do work after that method returns, you'll pass in a parameter with the work to be done next. Something like:
public void ShowMessageBoxAsync(string message, Action afterAction)
{
Device.BeginInvokeOnMainThread(() =>
{
// See "Chaining Tasks ..." link. Use "afterAction" as "continuation".
... DisplayAlert("Error", message, "OK", "Cancel") ...
});
}
"afterAction" is what will become the "continuation".
Sorry, I don't have the details at my fingertips - see above link.
xamarin.forms. Anyone who understands C# async/await, just needs to know that "Device.BeginInvokeOnMainThread" is a mechanism for switching to UI thread. OP shouldn't be trying to mix that with C# async/await, so needs to be pointed in a different direction. I've laid out some alternatives in my answer; if R.Cats wants more details on one of those, hopefully someone else can add a specific answer with those details. - ToolmakerSteveDevice.InvokeOnMainThreadAsync- user1623521