多个MessageDialog应用程序崩溃

Qer*_*rts 4 c# windows-runtime

MessageDialogues在我的应用程序的几个地方使用.问题是,只要有任何MessageDialog(或系统警报,如功能警告)处于活动状态而另一个人MessageDialog被调用,应用程序就会毫无例外地崩溃或者崩溃UnathorizedAccessException.

这就是我如何调用MessageDialog:

CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
    MessageDialog msg2 = new MessageDialog(_resourceLoader.GetString("MsgGPSUnavailable"));
    msg2.ShowAsync();
});
Run Code Online (Sandbox Code Playgroud)

我以为我应该等待对话框的关闭,但是通过使用Dispatcher我将这个对话框排队到主UI线程,它自己处理这个?感谢您对此问题的任何解释.

编辑 - 我一步一步地进行了下面的代码,它包含在同一个类中.当我运行app时,会调用LoadDataToModel.这没关系,msgGPSDisabled显示了对话框.之后引发事件并调用locator_StatusChanged.这也没问题,并显示对话框.现在奇怪的部分.当我不在LoadDataToModel中调用msgGPSDisabled且仅在locator_StatusChanged中调用msgGPSDisabled时,app会在显示对话框后立即崩溃.没有例外,第47行打开了App.gics(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();
}
Run Code Online (Sandbox Code Playgroud)

Fil*_*kun 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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)