Несколько вызовов MessageDialog вызывают сбой в Windows Phone 8.1

Я разрабатываю универсальное приложение, которое использует MVVM-Light. Я вызываю WebServices из ViewModels и выкидываю исключения, с которыми сталкиваются вызовы в WebServices, в ViewModels: TimeOut, Wrong URL, Server Exception, ...

Я создал класс "ExceptionsMsgHelper.cs", который централизует сообщения, отображаемые для каждого из этих исключений через MessageDialog.

Моя домашняя страница основана на сводной таблице, содержащей несколько данных: некоторые веб-службы вызываются асинхронно. Я так и сталкиваюсь с падением, если показываю исключение в MessageDialog через класс "ExceptionsMsgHelper.cs", тогда как предыдущее исключение также отображается в другом 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);
            });
        }           
    }

=> Но и в этом случае я всегда получаю одно и то же исключение.

Код сейчас:

    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
    }

=> И это работает для меня.

Но, как говорит автор, это, вероятно, не лучшее решение:

Закройте существующий диалог, когда вам нужно открыть новый. Это самый простой и, возможно, лучший вариант, хотя вы рискуете отменить диалог, который может быть как-то важным в зависимости от того, о чем ваши диалоги. Поставьте в очередь диалоги, чтобы старые не удалялись, а новые показывались после того, как старые были уволены. Этот будет гарантировать, что все диалоги закрыты пользователем, но это может быть проблемой, если ваше приложение может как-то начать показывать сотни диалогов. Открывайте только новую, если она еще не отображена. Теперь это рискует, что более новое сообщение не отображается, что звучит более проблематично, чем первый вариант.

=> Я хотел бы понять, почему я не могу применить одно из 2 первых решений, которое кажется более адаптированным

1 ответ

Конечно, вы не можете отображать 2 или более диалоговых сообщений одновременно (ограничения Windows Phone). более того MesssageDialog в Windows Phone 8.1, вероятно, ошибка и не может быть закрыта.

Если закрытие предыдущего диалога будет решением для вас, попробуйте использовать ContentDialog вместо MessageDialog, Проверьте мой ответ в этой теме: Закрытие MessageDialog программно в WP 8.1 RT

Я думаю, что это решит вашу проблему.