I use MessageDialogues
at several places over my app. Problem is, whenever is any MessageDialog
(or system alert, such as capability warning) active and another my MessageDialog
is called, application crashes without exception or with UnathorizedAccessException
.
This is, how I call MessageDialog:
CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
MessageDialog msg2 = new MessageDialog(_resourceLoader.GetString("MsgGPSUnavailable"));
msg2.ShowAsync();
});
I thought I should wait for closure of the dialog, but by using Dispatcher
I queue this dialog to the main UI thread, which handles this itself, or not? Thanks for any explanation of this problem.
Edit - I proceeded step by step and got following code, which is contained in same class. When I run app, LoadDataToModel is called. This is ok and dialog is shown by msgGPSDisabled. After that is event raised and locator_StatusChanged is called. This is ok too and dialog is shown. Now the strange part. When I do not call msgGPSDisabled in LoadDataToModel and only in the locator_StatusChanged, app crashes immediately after showing dialog. No exception and App.g.i.cs is opened on line 47 (DEBUG && !DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION). Even if I use try-catch whereever it could be used. When I use msgGPSDisabled without Dispatcher in locator_StatusChanged, exceptions is raised. Not catchable, "item not found"
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();
}
Your lambda should still await the async call, so that when the dispatcher runs it, it won't continue until the message box is closed.
I haven't tried it, but this should help (notice the usage of
async
andawait
keywords):EDIT:
As Filip already explained, you can't have more than one message box displayed at the same time. He also suggested a couple of approaches you could use to avoid the problem.
In your scenario (reporting about GPS status changes) it would probably be a better idea to display the status as a label inside your UI as you don't really need the user to respond to it in any way. You could even collect the values as they change in a list and display them using an
ItemsControl
so that the user could observe the history of changes (potentially with a timestamp). It all depends on what you want to achieve.Two
MessageDialogs
can't be displayed at the same time. You have a few options if you want to continue usingMessageDialogs
and for all it would be best to have some sort ofMessageDialogService
to manage calls to bring up dialogs:If you'd like to go with the queue option - you could use this code: