Multiple MessageDialog app crash

元气小坏坏 提交于 2019-12-05 12:39:44

Two MessageDialogs can't be displayed at the same time. You have a few options if you want to continue using MessageDialogs and for all it would be best to have some sort of MessageDialogService to manage calls to bring up dialogs:

  • Close existing dialog when you need to open a new one. This is the simplest option and possibly the best, although you risk cancelling a dialog that might be somehow important depending on what your dialogs are about.
  • Queue up dialogs so the old ones don't get dismissed, but the new ones show up after the old ones were dismissed. This one will make sure all dialogs are closed by the user, but that could be a problem if your app can somehow start showing hundreds of dialogs.
  • Only open a new one if there isn't one already displayed. Now this risks that a newer message is not shown, which sounds more problematic than the first option.

If you'd like to go with the queue option - you could use this code:

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;
        }
    }
}

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 and await keywords):

CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
{
    MessageDialog msg2 = new MessageDialog(_resourceLoader.GetString("MsgGPSUnavailable"));
    await msg2.ShowAsync();
});

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!