我在我的应用上的几个地方使用MessageDialogues
。问题是,只要任何MessageDialog
(或系统警报,例如功能警告)处于活动状态,而另一个MessageDialog
被调用,应用程序就会毫无例外地或UnathorizedAccessException
崩溃。
这就是我如何调用MessageDialog:
CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
MessageDialog msg2 = new MessageDialog(_resourceLoader.GetString("MsgGPSUnavailable"));
msg2.ShowAsync();
});
我以为我应该等待关闭对话框,但是通过使用Dispatcher
我将此对话框排队到主UI线程,它自己处理这个问题?感谢您对此问题的任何解释。
编辑 - 我继续一步一步地获得以下代码,该代码包含在同一个类中。当我运行app时,会调用LoadDataToModel。这没关系,msgGPSDisabled显示了对话框。之后引发事件并调用locator_StatusChanged。这也没问题,并显示对话框。 现在奇怪的部分。当我不在LoadDataToModel中调用msgGPSDisabled且仅在locator_StatusChanged中调用时,应用程序在显示对话框后立即崩溃。没有例外,第47行打开了App.g.i.cs(DEBUG&&!DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION)。即使我使用try-catch,也可以使用它。当我在locator_StatusChanged中使用不带Dispatcher的msgGPSDisabled时,会引发异常。不可捕捉,“找不到物品”
public async Task LoadDataToModel()
{
await msgGPSDisabled();
this.IsBusy = true;
await LoadDataGarvis(Stations); //rozparsuje raw data a načte je do modelu
InitializePins();
this.IsBusy = false;
}
void locator_StatusChanged(Geolocator sender, StatusChangedEventArgs args)
{
switch (sender.LocationStatus)
{
case Windows.Devices.Geolocation.PositionStatus.Disabled:
try
{
CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
{
await msgGPSDisabled();
IsGPSBusy = false;
IsGPS = false;
});
}
catch (UnauthorizedAccessException)
{
throw;
}
catch (Exception) {throw; }
case Windows.Devices.Geolocation.PositionStatus.NoData:
CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
{
await msgGPSUnavailable();
});
}
}
private async Task msgGPSDisabled()
{
MessageDialog sss = new MessageDialog(_resourceLoader.GetString("MsgGPSDisabled"));
await sss.ShowAsync();
}
答案 0 :(得分:7)
无法同时显示两个MessageDialogs
。如果您想继续使用MessageDialogs
,可以选择几个选项,而最重要的是,可以使用某种MessageDialogService
来管理调用以显示对话框:
如果您想使用队列选项 - 您可以使用以下代码:
using System;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.UI.Popups;
using Windows.UI.Xaml;
namespace WinRTXamlToolkit.Controls.Extensions
{
/// <summary>
/// MessageDialog extension methods
/// </summary>
public static class MessageDialogExtensions
{
private static TaskCompletionSource<MessageDialog> _currentDialogShowRequest;
/// <summary>
/// Begins an asynchronous operation showing a dialog.
/// If another dialog is already shown using
/// ShowAsyncQueue or ShowAsyncIfPossible method - it will wait
/// for that previous dialog to be dismissed before showing the new one.
/// </summary>
/// <param name="dialog">The dialog.</param>
/// <returns></returns>
/// <exception cref="System.InvalidOperationException">This method can only be invoked from UI thread.</exception>
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;
}
}
}
答案 1 :(得分:0)
你的lambda应该等待异步调用,这样当调度程序运行它时,它将不会继续,直到消息框关闭。
我还没有尝试过,但这应该会有所帮助(请注意async
和await
个关键字的使用情况:
CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
{
MessageDialog msg2 = new MessageDialog(_resourceLoader.GetString("MsgGPSUnavailable"));
await msg2.ShowAsync();
});
修改强>
正如Filip已经解释过的那样,您不能同时显示多个消息框。他还提出了一些可以用来避免这个问题的方法。
在您的方案中(报告GPS状态更改),最好将状态显示为UI内的标签,因为您实际上并不需要用户以任何方式对其进行响应。您甚至可以在列表中更改时收集值并使用ItemsControl
显示它们,以便用户可以观察更改历史记录(可能带有时间戳)。这一切都取决于你想要达到的目标。