3

我有一个 ViewModel,它以同步方法实例化一个事件。该事件向 UI 发出信号,我们需要用户回答“是”或“否”,然后才能继续。

我正在尝试显示 aMessageDialog并等到用户提供答案 - 是或否。我很难做到这一点。我目前正在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;
}

我试过了:

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);

但这失败了同样的例外。

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

MessageDialog md = new MessageDialog(question);
md.Commands.Add(new UICommand("Yes", CommandInvokedHandler));
md.Commands.Add(new UICommand("No", CommandInvokedHandler));
await md.ShowAsync();

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

在此先感谢您的帮助。

4

1 回答 1

8

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

由于您的方法未在 上执行,Dispatcher您将需要手动调用其上的代码。为了避免重构为回调模式,您可以使用 aTaskCompletionSource(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;
于 2013-06-24T12:08:00.807 回答