2012-10-04 31 views
23

Estoy tratando de implementar try again/cancel cuadro de diálogo en Windows 8. El cuadro de diálogo muestra bien la primera vez, pero al hacer clic en try again y fallar nuevamente, obtengo una excepción de acceso denegado al llamar a ShowAsync. No sé por qué, pero a veces es extraño, el código funciona bien y no obtengo la excepción cuando pongo puntos de corte. realmente despistado aquíMessageDialog ShowAsync arroja una excepción accessdenied en el segundo cuadro de diálogo

aquí está el código.

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

Respuesta

24

bien he encontrado una solución rápida,

definir un Varialble clase IAsyncOperation

IAsyncOperation<IUICommand> asyncCommand = null; 

y configurarlo para que el método ShowAsync de MessageDialog

asyncCommand = msg.ShowAsync(); 

En el controlador de comandos para volver a intentar/inténtelo de nuevo compruebe si asyncCommand no está null y cancelar la última operación si es necesario

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

Por favor, déjenme si hay un mejor enfoque para esto.

+0

Para prevenir el "Uso de variable local no asignada 'asyncCommand'", que tuvieron que asignar null para asyncCommand cuando está asignado. –

+1

Nota al margen: tenía mi propia tarea Que se ejecuta en un solo hilo y solo estaba haciendo ONE ShowAsync de UN hilo a la vez. Aparentemente, si una ShowAsync finaliza en la trama 1 y una segunda ShowAsync se inicia en la trama 2, puede aparecer un error aleatorio Acceso denegado: /. Sin embargo, cancela manualmente trabajos. – RelativeGames

+0

@clay Actualicé el código anterior – Syler

3

Hay una respuesta para esto en los foros de MSDN que podrían ayudarlo aquí.

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

Estoy teniendo un problema similar, pero mis llamadas showAsync están en funciones separadas en hilos separados, así que no puedo soltar un hecho() allí no creo ...

+1

intente usar una variable de instancia y mantenga una referencia al asyncCommand y verifique si el comando no es nulo. podría funcionar. – Syler

+1

Sí, eso funciona en mi caso. Parece masivamente hacky aunque –

3

Hace algunos días me enfrentaba a este mismo problema, lo resuelvo esperando el ShowAsync y luego hago la llamada recursiva que abre el MessageDialog nuevamente.

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!

9

llego tarde a la fiesta, pero aquí es una manera en la que siempre se puede esperar el resultado del cuadro de diálogo, así como no tiene que preocuparse acerca de llamar a demasiados en una fila:

En primer lugar definir una estática variable y método en su aplicación:

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

Ahora, puede pasar en cualquier cuadro de diálogo y esperar siempre la ejecución. Es por eso que esto devuelve un bool en lugar de vacío. No tendrá que preocuparse por las colisiones entre los múltiplos. ¿Por qué no hacer que este método acepte una cadena? Debido al título y a los controladores de comando Sí/No que puede asignar al cuadro de diálogo específico que está utilizando.

invocación como:

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

Otra solución:

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! ¡esta es la única solución que funciona para mí! –

Cuestiones relacionadas