【问题标题】:MessageDialog - needs to wait for user inputMessageDialog - 需要等待用户输入
【发布时间】:2014-05-26 13:07:26
【问题描述】:

我有一个 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;
}

我试过了:

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 的异步行为加上我的同步例程加上跨线程让我感到困惑。我想知道是否有人可以概述在我的后端 ViewModel 中继续同步方法之前,我需要做什么来等待 MessageDialog 上的用户输入。

提前感谢您的帮助。

【问题讨论】:

    标签: c# microsoft-metro async-await messagedialog


    【解决方案1】:

    请参阅 Win8 C# Metro dispatcher and RPC_E_WRONG_THREADCoreDispatcher.RunAsync

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

    【讨论】:

    • 感谢您的回复,但我需要等待用户输入才能继续执行代码。如果我等待 Dispather.RunAsync 调用,则不会显示 MessageDialog 并且 UI 线程会锁定。有什么建议么?提前致谢。
    • 再次感谢您的快速回复。不幸的是,这仍然没有等待,我有一个返回 canSwitch;此调用之后的语句以及在显示 MessageDialog 之前调用它,如果我等待 Dispatcher.RunAsync 调用,我将再次锁定 UI 线程。还有其他想法吗?
    • 你可以做的是使用TaskCompletionSource(T)Dispatcher 运行。查看我的编辑。
    • 再次感谢您的快速响应,但这也不会显示我的 MessageDialog 并锁定 UI 线程...
    • 其他有趣的事情,如果我从 UI 类的初始化中调用上面的代码,这将按预期运行。但是,当我在后端 ViewModel(在不同的程序集中)中引发事件后运行的 UI 事件处理程序中调用时,我得到了锁定的行为。有任何想法吗?再次感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-26
    • 2016-09-26
    • 1970-01-01
    • 1970-01-01
    • 2015-02-19
    • 2013-05-25
    • 2016-05-06
    相关资源
    最近更新 更多