【问题标题】:Second DisplayAlert hanging第二个 DisplayAlert 挂起
【发布时间】:2018-12-05 01:04:21
【问题描述】:

我正在使用 Xamarin Forms 构建应用程序,我遇到了 DisplayAlert 触发一次但第二次挂起的问题。

请考虑以下代码:

ThisThingClickedCommand = new Command(
async () =>
{
    var continue = true;
    if (SomeVariable.is_flagged == 0)
    {
        continue = await PageSent.DisplayAlert("User Question", "This is a question for the user", "Yes", "No");
    }

    if (continue)
    {
        Debug.WriteLine("This debug fires");
        var AnswerToSecondQuestion = await PageSent.DisplayAlert("Second Question", "This is a second question for the user", "Yes", "No");
        if (AnswerToSecondQuestion)
        {
            // Do more things
        }
        Debug.WriteLine("This one does not :(");
    }
}),

上面的代码已经在一个项目中存在了很长时间,并且似乎一直有效,直到最近更新到 Visual Studio 2017 以及随后的一些新的目标 Windows 版本。

当我在 Windows 上启动应用程序(目前在其他设备上未经测试)并且这段特定的代码运行时,第一个 DisplayAlert 显示没有问题,但第二个 DisplayAlert 从未显示并且应用程序挂起等待它回答(我假设)。

如果有人能解释如何解决这个问题,我将不胜感激,但如果他们也能解释为什么会发生这种情况,那就更好了。

【问题讨论】:

    标签: c# xamarin.forms uwp async-await xamarin.uwp


    【解决方案1】:

    避免async void 触发和忘记方法,这是命令操作委托将转换为的方法。事件处理程序是一个例外。

    参考Async/Await - Best Practices in Asynchronous Programming

    创建事件和处理程序

    private event EventHandler raiseAlerts = delegate { };
    private async void OnRaiseAlerts(object sender, EventArgs args) {
        var _continue = true;
        if (SomeVariable.is_flagged == 0) {
            _continue = await PageSent.DisplayAlert("User Question", "This is a question for the user", "Yes", "No");
        }
    
        if (_continue) {
            Debug.WriteLine("This debug fires");
            var AnswerToSecondQuestion = await PageSent.DisplayAlert("Second Question", "This is a second question for the user", "Yes", "No");
            if (AnswerToSecondQuestion) {
                // Do more things
            }
            Debug.WriteLine("This one does not :(");
        }
    }
    

    订阅活动。很可能在构造函数中

    raiseAlerts += OnRaiseAlerts
    

    并在命令动作委托中引发事件

    ThisThingClickedCommand = new Command(() => raiseAlerts(this, EventArgs.Empty));
    

    现在至少应该能够捕获任何抛出的异常,以了解存在的问题(如果有的话)。

    【讨论】:

    • Rudy 的解决方案似乎已经解决了这个问题,因此接受了他的回答。我将使用您提供的信息来使我的代码也成为“最佳实践”。感谢您的努力。
    【解决方案2】:

    使用 Device.BeginInvokeOnMainThread 确保 UI 线程处理第二次调用:

         ThisThingClickedCommand = new Command(
        async ()=>
        {
            var continue = true;
            if (SomeVariable.is_flagged == 0)
            {
                continue = await PageSent.DisplayAlert("User Question", "This is a question for the user", "Yes", "No");
            }
    
            if (continue)
            {
                Debug.WriteLine("This debug fires");
    
    Device.BeginInvokeOnMainThread(async () =>
                var AnswerToSecondQuestion = await PageSent.DisplayAlert("Second Question", "This is a second question for the user", "Yes", "No");
                if (AnswerToSecondQuestion)
                {
                    // Do more things
                }
                Debug.WriteLine("This one does not :(");
            });
        }),
    

    确实,在等待之后,如果您想要操作操作 UI 的方法或属性,则需要确保在 UI 线程上继续执行

    【讨论】:

    • 经过一些代码移动后,此解决方案有效。如果您不介意更新答案以解释为什么这对未来的人们有用。我现在接受这个答案。
    猜你喜欢
    • 2017-05-27
    • 1970-01-01
    • 2016-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多