2012-10-04 11 views
23

Sto tentando di implementare nuovamente la finestra di dialogo di prova in Windows 8. La finestra di dialogo viene visualizzata correttamente la prima volta, ma quando si fa nuovamente clic si verifica un errore di accesso negato alla chiamata ShowAsync. Non so perché, ma è strano a volte il codice funziona bene e non ottengo l'eccezione quando inserisco i breakpoint. davvero clueless quiMessageDialog ShowAsync genera un'eccezione accessdenied nella seconda finestra di dialogo

ecco il codice.

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

risposta

24

Va bene ho trovato una soluzione rapida,

definire una classe IAsyncOperation varialble

IAsyncOperation<IUICommand> asyncCommand = null; 

e impostarlo al metodo ShowAsync di MessageDialog

asyncCommand = msg.ShowAsync(); 

Nel gestore di comando per riprovare/riprovare controllare se asyncCommand non è Nullare e annullare l'ultima operazione, se necessario

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

Per favore fatemi se c'è un approccio migliore a questo.

+0

Per evitare di ottenere "Uso di non assegnata variabile locale 'asyncCommand'", ho dovuto assegnare null a asyncCommand quando viene assegnato. –

+1

Nota a margine: il mio task era in esecuzione in un singolo thread e stavo facendo ONE ONE ShowAsync da un thread alla volta. Apparentemente se uno ShowAsync termina nel frame 1 e un secondo ShowAsync inizia nel frame 2, può comparire un errore di accesso negato in modo casuale: /. Tuttavia, la cancellazione manuale funziona. – RelativeGames

+0

@clay Ho aggiornato il codice sopra – Syler

3

C'è una risposta per questo sui forum MSDN che potrebbe aiutarti.

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

Sto avendo un problema simile, ma le mie chiamate showAsync sono in funzioni separate in thread separati, quindi non posso cadere un fatto() in là non credo ...

+1

provare a utilizzare una variabile di istanza e mantenere un riferimento a asyncCommand e verificare se il comando non è nullo. potrebbe funzionare. – Syler

+1

Sì, questo funziona nel mio caso. Sembra un hacky massivo anche se –

3

Ho dovuto affrontare lo stesso problema alcuni giorni fa e lo risolvo attendendo ShowAsync e quindi effettuando la chiamata ricorsiva che apre nuovamente MessageDialog.

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

Spero che questo aiuto!

9

Sono in ritardo alla festa, ma ecco un modo in cui si può sempre aspettare il risultato della finestra di dialogo, così come non c'è bisogno di preoccuparsi di chiamare troppi consecutive:

prima definire un statica variabile e metodo nell'applicazione:

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

Ora è possibile passare in qualsiasi finestra di dialogo e attendere sempre l'esecuzione. Questo è il motivo per cui questo restituisce un bool piuttosto che vuoto. Non dovrai preoccuparti delle collisioni tra multipli. Perché non fare in modo che questo metodo accetti una stringa? A causa del titolo e dei comandi di comando Sì/No che è possibile assegnare alla finestra di dialogo specifica che si sta utilizzando.

Invoke come ad esempio:

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

o

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); 
2

Un'altra soluzione:

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; 
     }); 
} 
+0

Thx! questa è l'unica soluzione, che funziona per me! –