I have a ViewModel which instantiates an event in a synchronous method. The event signals to the UI that we need a "Yes" or "No" answer from the user before continuing.
I am trying to display a MessageDialog
and wait until the user provides an answer - Yes or No. I am having a difficult time doing this. I currently get an UnauthorizedAccessException
when trying to do this.
Here's a look at the code in the UI:
async Task<bool> Instance_SwitchConfirmation(string question)
{
MessageDialog md = new MessageDialog(question);
md.Commands.Add(new UICommand("Yes", CommandInvokedHandler));
md.Commands.Add(new UICommand("No", CommandInvokedHandler));
md.ShowAsync();
return this.canSwitch;
}
async void CommandInvokedHandler(IUICommand command)
{
this.canSwitch = command.Label == "Yes" ? true : false;
}
I have tried:
var uiContext = TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory.StartNew(() => {
MessageDialog md = new MessageDialog(question);
md.Commands.Add(new UICommand("Yes", CommandInvokedHandler));
md.Commands.Add(new UICommand("No", CommandInvokedHandler));
md.ShowAsync();
},
new System.Threading.CancellationToken(),
TaskCreationOptions.PreferFairness, uiContext);
but this fails with the same exception.
Lastly, if I simply await the MessageDialog like so, the dialog is not displayed and the UI thread locks up.
MessageDialog md = new MessageDialog(question);
md.Commands.Add(new UICommand("Yes", CommandInvokedHandler));
md.Commands.Add(new UICommand("No", CommandInvokedHandler));
await md.ShowAsync();
If MessageDialog
had a synchronous version of Show()
I would be fine but the asynchrnous behvaior of MessageDialog
coupled with my synchrounous routine, coupled with cross threading is confusing me. I'm wondering if someone can outline what I need to do to wait for user input on a MessageDialog
before continuing a synchronous method in my backend ViewModel.
Thanks in advance for the help.
See Win8 C# Metro dispatcher and RPC_E_WRONG_THREAD and
CoreDispatcher.RunAsync
.Since your method isn't executing on the
Dispatcher
you're going to need to invoke the code on it manually. In order to avoid refactoring into a callback pattern you can use aTaskCompletionSource(T)
to set the result and the background thread will continue after the result is set.