MessageDialog ShowAsync throws accessdenied exception on second dialog

14,867

Solution 1

Okay I found a quick solution,

define a IAsyncOperation class varialble

IAsyncOperation<IUICommand> asyncCommand = null;

and set it to the ShowAsync method of MessageDialog

asyncCommand = msg.ShowAsync();

In the command handler for retry/try again check if asyncCommand is not null and cancel the last operation if necessary

if(asyncCommand != null)
{
   asyncCommand.Cancel();
}

Please let me if there is a better approach to this.

Solution 2

I am late to the party, but here's a way where you can always await the result of the dialog box, as well as not need to worry about calling too many in a row:

First define a static variable and method in your application:

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

Now, you can pass in any dialog box and always await execution. This is why this returns a bool rather than void. You won't have to worry about collisions between multiples. Why not make this method accept a string? Because of title, and Yes/No command handlers that you may assign into the specific dialog box you are using.

Invoke such as:

await App.ShowDialog(new MessageDialog("FOO!"));

or

var dlg = new MessageDialog("FOO?", "BAR?");
dlg.Commands.Add(new UICommand("Yes", new UICommandInvokedHandler(YesHandler)));
dlg.Commands.Add(new UICommand("No", new UICommandInvokedHandler(NoHandler)));
await App.ShowDialog(dlg);

Solution 3

There is an answer for this on the MSDN forums that might help you here.

http://social.msdn.microsoft.com/Forums/en-US/winappswithhtml5/thread/c2f5ed68-aac7-42d3-bd59-dbf2673dd89b

I'm having a similar problem but my showAsync calls are in separate functions on separate threads so I can't drop a done() in there I don't think...

Solution 4

I was facing this same issue some days ago, and i solve it awaiting the ShowAsync and then making the recursive call that open the MessageDialog again.

public async void ShowDlg(){
    Action cmdAction = null;
    var msgDlg = new MessageDialog("Content.", "Title");
    msgDlg.Commands.Add(new UICommand("Retry", (x) => {
    cmdAction = () => ShowDlg();
    }));
    msgDlg.Commands.Add(new UICommand("Cancel", (x) => {
    cmdAction = () => <Action associated with the cancel button>;
    }));
    msgDlg.DefaultCommandIndex = 0;
    msgDlg.CancelCommandIndex = 1;

    await msgDlg.ShowAsync();
    cmdAction.Invoke();
}

Hope this help!

Solution 5

Another solution:

private bool _messageShowing = false;

// ...

if (!_messageShowing)
{
    _messageShowing = true;
    var messageDialog = new MessageDialog("Example");

    // ... "messageDialog" initialization

    Task<IUICommand> showMessageTask =  messageDialog.ShowAsync().AsTask();
    await showMessageTask.ContinueWith((showAsyncResult) =>
        {
            _messageShowing = false;
        });
}
Share:
14,867

Related videos on Youtube

Syler
Author by

Syler

Updated on June 12, 2020

Comments

  • Syler
    Syler about 4 years

    I am trying to implement try again/cancel dialog box in windows 8. The dialog box shows fine the first time, but on clicking try again and failing again, I get a access denied exception on calling ShowAsync. I don't know why, but its strange sometimes the code works fine and I don't get the exception when I put breakpoints. really clueless here

    here is the code.

        async void DismissedEventHandler(SplashScreen sender, object e)
        {
            dismissed = true;
            loadFeeds();
        }
        private async void loadFeeds()
        {
            await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
            {
                try
                {
                    RSSDataSource rssDataSource = (RSSDataSource)App.Current.Resources["RSSDataSource"];
                    if (rssDataSource != null)
                    {
                        await rssDataSource.DownloadFeeds();
                        await rssDataSource.GetFeedsAsync();
                    }
    
                    AdDataSource ads = (AdDataSource)App.Current.Resources["AdDataSource"];
    
                    if (ads != null)
                    {
                        await ads.DownloadAds();
                    }
                    rootFrame.Navigate(typeof(HomePageView));
    
                    Window.Current.Content = rootFrame;
                }
                catch
                {
                    ShowError();
                }
    
            });
        }
        async void ShowError()
        {
            // There was likely a problem initializing
            MessageDialog msg = new MessageDialog(CONNECTION_ERROR_MESSAGE, CONNECTION_ERROR_TITLE);
    
            // Add buttons and set their command handlers
            msg.Commands.Add(new UICommand(COMMAND_LABEL_RETRY, new UICommandInvokedHandler(this.CommandInvokedHandler)));
            msg.Commands.Add(new UICommand(COMMAND_LABEL_CLOSE, new UICommandInvokedHandler(this.CommandInvokedHandler)));
            // Set the command to be invoked when a user presses 'ESC'
            msg.CancelCommandIndex = 0;
    
            await msg.ShowAsync();
        }
    
        /// <summary>
        /// Callback function for the invocation of the dialog commands
        /// </summary>
        /// <param name="command">The command that was invoked</param>
        private void CommandInvokedHandler(IUICommand command)
        {
            string buttonLabel = command.Label;
            if (buttonLabel.Equals(COMMAND_LABEL_RETRY))
            {
                loadFeeds();
            }
            else
            {
                // Close app
                Application.Current.Exit();
            }
        }
    
  • Syler
    Syler over 11 years
    try using an instance variable and hold a reference to the asyncCommand and check if the command is not null. it might work.
  • B. Clay Shannon-B. Crow Raven
    B. Clay Shannon-B. Crow Raven over 11 years
    To prevent getting "Use of unassigned local variable 'asyncCommand'", I had to assign null to asyncCommand when it is assigned.
  • RelativeGames
    RelativeGames over 10 years
    Side note : I had my own task que running in a single thread and I was only doing ONE ShowAsync from ONE thread at a time. Apparently if one ShowAsync ends in frame 1 and a second ShowAsync starts in frame 2, a random Access Denied error can pop :/. Manually canceling works though.
  • Chris Bordeman
    Chris Bordeman about 9 years
    This works perfectly in my scenario where the second dialog was not really nested, but instead shown in the callback action of the first UICommand.