我开发了一个使用MVVM-Light的通用应用程序。我从ViewModels调用WebServices,并将 WebServices 调用遇到的异常抛出给 ViewModels:TimeOut、Wrong URL、Server Exception,...
我创建了一个“ ExceptionsMsgHelper.cs ”类,它通过MessageDialog集中为每个异常显示的消息。
我的主页基于包含多个数据的 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))”
我一直在寻找解决方案来解决它:
- 使用“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);
});
}
}
=> 但在这种情况下,我总是遇到同样的异常。
- 使用扩展来排队 messagedialogs,就像在这里描述的一样(Multiple MessageDialog app crash)
现在的代码是:
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 个第一个解决方案