Несколько вызовов 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))"
Я так искал решения, чтобы исправить это:
- используйте "Dispatcter", как рекомендуется здесь ( WinRT - MessageDialog.ShowAsync вызовет исключение UnauthorizedAccessException в моем пользовательском классе)
Код является:
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();
});
}
}
=> Но я всегда встречаю одно и то же исключение.
- используйте команду "IAsyncOperation", чтобы закрыть предыдущий MessageDialog, как рекомендуется здесь ( MessageDialog ShowAsync генерирует исключение accessdenied во втором диалоге)
С этим кодом:
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);
});
}
}
=> Но и в этом случае я всегда получаю одно и то же исключение.
- используйте расширение, чтобы поставить в очередь сообщения сообщений, как описано здесь ( множественный сбой приложения 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 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
Я думаю, что это решит вашу проблему.