MessageDialog - 需要等待用户输入

use*_*154 3 c# messagedialog async-await microsoft-metro

我有一个ViewModel,它在同步方法中实例化一个事件.该事件向UI发出信号,表示在继续之前我们需要来自用户的"是"或"否"回答.

我试图显示MessageDialog并等待用户提供答案 - 是或否.我很难做到这一点.我目前正UnauthorizedAccessException试图这样做.

以下是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;
}
Run Code Online (Sandbox Code Playgroud)

我试过了:

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);
Run Code Online (Sandbox Code Playgroud)

但这失败了同样的例外.

最后,如果我只是等待MessageDialog,则不显示对话框并且UI线程锁定.

MessageDialog md = new MessageDialog(question);
md.Commands.Add(new UICommand("Yes", CommandInvokedHandler));
md.Commands.Add(new UICommand("No", CommandInvokedHandler));
await md.ShowAsync();
Run Code Online (Sandbox Code Playgroud)

如果MessageDialog有一个同步版本的Show()我会没事的但是异步的behvaior MessageDialog加上我的同步例程,加上交叉线程让我感到困惑.我想知道MessageDialog在我的后端ViewModel中继续使用同步方法之前是否有人可以概述我需要做什么来等待用户输入.

在此先感谢您的帮助.

Dus*_*gen 8

请参阅Win8 C#Metro调度程序和RPC_E_WRONG_THREAD和CoreDispatcher.RunAsync.

由于您的方法没有执行,因此Dispatcher您需要手动调用其上的代码.为了避免重构为回调模式,您可以使用a TaskCompletionSource(T)来设置结果,后台线程将在设置结果后继续.

var tcs = new TaskCompletionSource<bool>();
var dialogTask = tcs.Task;

MessageDialog md = new MessageDialog(question);
md.Commands.Add(new UICommand("Yes"));
md.Commands.Add(new UICommand("No"));

Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () => {
    var result = await md.ShowAsync();
    var canSwitch = result.Label == "Yes";
    tcs.SetResult(canSwitch);
});

var result = await dialogTask;
return result;
Run Code Online (Sandbox Code Playgroud)