在Windows Phone 8.1下多次调用MessageDialog会导致崩溃

时间:2015-10-15 23:27:34

标签: windows-phone-8.1 mvvm-light win-universal-app messagedialog windows-8.1-universal

我开发了一个使用 MVVM-Light 通用应用。我从 ViewModels 调用 WebServices ,并将WebServices上的调用遇到的异常抛给ViewModels:TimeOut,错误的URL,服务器异常,......

我创建了一个类" ExceptionsMsgHelper.cs "它通过 MessageDialog 集中显示为每个例外显示的消息。

我的HomePage基于包含多个数据的Pivot:某些Web服务是异步调用的。如果我通过类" ExceptionsMsgHelper.cs "在MessageDialog中显示异常,我就会遇到崩溃,而之前的异常也会在另一个MessageDialog中显示。

这是我原来课程的一部分:

    public class ExceptionsMsgHelper
    {
        public async static void MsgboxWebserviceErrors(WebServiceErrorsException wseE, string errors)
        {
            Windows.UI.Popups.MessageDialog msgbox =
            new Windows.UI.Popups.MessageDialog("The Websercice '" + wseE.WebService + "' has returned errors : \n" + errors,
                "Unexpected data");        
            await msgbox.ShowAsync();
        }
    }

=>如果我两次调用" msgbox.ShowAsync()",我得到" System.UnauthorizedAccessException"例外:使用消息"访问被拒绝。 (HRESULT异常:0x80070005(E_ACCESSDENIED))"

我已经寻找解决方案以解决问题:

代码是:

    public class ExceptionsMsgHelper
    {
        public async static void MsgboxWebserviceErrors(WebServiceErrorsException wseE, string errors)
        {
            Windows.UI.Popups.MessageDialog msgbox =
            new Windows.UI.Popups.MessageDialog("The Websercice '" + wseE.WebService + "' has returned errors : \n" + errors,
                "Unexpected data");        
            CoreDispatcher dispatcher = CoreWindow.GetForCurrentThread().Dispatcher;
            dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
            {
                await msgbox.ShowAsync();
            });
        }
    }

=>但我总是遇到同样的例外。

使用此代码:

    public class ExceptionsMsgHelper
    {
        private static IAsyncOperation<IUICommand> messageDialogCommand = null;
        public async static Task<bool> ShowDialog(MessageDialog dlg)
        {

            // Close the previous one out
            if (messageDialogCommand != null)
            {
                messageDialogCommand.Cancel();
                messageDialogCommand = null;
            }

            messageDialogCommand = dlg.ShowAsync();
            await messageDialogCommand;
            return true;
        }

        public async static void MsgboxWebserviceErrors(WebServiceErrorsException wseE, string errors)
        {
            Windows.UI.Popups.MessageDialog msgbox =
            new Windows.UI.Popups.MessageDialog("The Websercice '" + wseE.WebService + "' has returned errors : \n" + errors,
                "Unexpected data");        
            CoreDispatcher dispatcher = CoreWindow.GetForCurrentThread().Dispatcher;
            dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
            {
                await ShowDialog(msgbox);
            });
        }           
    }

=&GT;但在这种情况下,我总是得到同样的例外。

代码现在是:

    public class ExceptionsMsgHelper
    {
        public async static void MsgboxWebserviceErrors(WebServiceErrorsException wseE, string errors)
        {
            Windows.UI.Popups.MessageDialog msgbox =
            new Windows.UI.Popups.MessageDialog("The Websercice '" + wseE.WebService + "' has returned errors : \n" + errors,
                "Unexpected data");   
            await MessageDialogExtensions.ShowAsyncQueue(msgbox);
        }
    }

    public static class MessageDialogExtensions
    {
        private static TaskCompletionSource<MessageDialog> _currentDialogShowRequest;
        public static async Task<IUICommand> ShowAsyncQueue(this MessageDialog dialog)
        {
            if (!Window.Current.Dispatcher.HasThreadAccess)
            {
                throw new InvalidOperationException("This method can only be invoked from UI thread.");
            }

            while (_currentDialogShowRequest != null)
            {
                await _currentDialogShowRequest.Task;
            }

            var request = _currentDialogShowRequest = new TaskCompletionSource<MessageDialog>();
            var result = await dialog.ShowAsync();
            _currentDialogShowRequest = null;
            request.SetResult(dialog);

            return result;
        }
    private static IAsyncOperation<IUICommand> messageDialogCommand = null;
    public async static Task<bool> ShowDialog(this MessageDialog dlg)
    {

        // Close the previous one out
        if (messageDialogCommand != null)
        {
            messageDialogCommand.Cancel();
            messageDialogCommand = null;
        }

        messageDialogCommand = dlg.ShowAsync();
        await messageDialogCommand;
        return true;
    }

    #endregion
    }

=&GT;这对我有用。

但就像它的作者说的那样,它可能不是最好的解决方案:

  

需要打开新对话框时关闭现有对话框。这是最简单的选项,也可能是最好的选项,尽管您可能会取消根据对话框的内容可能在某种程度上重要的对话框。   排队对话,以便旧的对象不被解雇,但新的对话在旧的被​​解雇后出现。这个将确保用户关闭所有对话框,但如果您的应用程序可以某种方式开始显示数百个对话框,则可能会出现问题。   如果尚未显示,则仅打开一个新的。现在这可能会导致没有显示更新的消息,这听起来比第一个选项更有问题。

=&GT;我想了解为什么我无法应用似乎更适应的2个第一个解决方案

1 个答案:

答案 0 :(得分:2)

当然,您无法同时显示2个或更多消息对话框(Windows Phone限制)。此外,Windows Phone 8.1上的MesssageDialog可能存在错误,无法关闭。

如果关闭上一个对话框将是您的解决方案,请尝试使用ContentDialog代替MessageDialog。请查看我在此主题中的答案:Closing MessageDialog programatically in WP 8.1 RT

我认为它可以解决你的问题。