2012-08-16 10 views
5

La aplicación My Win RT que ha trabajado con VS2012RC en una versión beta de Windows 8, ahora con las versiones finales de visual studio y Windows 8 pro el problema, que crear/abrir un archivo dentro de OnSuspending solo funciona si configuro un punto de interrupción de depurador en el método de creación de archivos.StorageFolder.CreateFileAsync falla cuando se le llama desde App.OnSuspending

private void OnSuspending(object sender, SuspendingEventArgs e){       
    var deferral = e.SuspendingOperation.GetDeferral();      
    if (null != m_document) Save(); 
    deferral.Complete(); 
} 

async void Save(){ 
    var folder = KnownFolders.DocumentsLibrary;  
    var file = await folder.CreateFileAsync(GetFileName(),Windows.Storage.CreationCollisionOption.ReplaceExisting);     

    var xDoc = GetXDocument(); 
    using (var stream = await file.OpenStreamForWriteAsync()){ 
     xDoc.Save(stream);      
    }   
} 
  • Si fijo un punto de interrupción en StorageFile file = await folder.CreateFileAsync(..., el depurador entra en el y si continúo, todo funciona bien.

  • Sin embargo, si no configuro un punto de interrupción, se creará el archivo, pero el contenido del xml no se guardará (el archivo descansa vacío).

  • Si configuro un punto de interrupción debajo de la línea StorageFile file = await folder.CreateFileAsync(..., ¡el depurador nunca entra!

¿Alguien tiene una idea? También probé una versión que usa folder.OpenStreamForWriteAsync, con el mismo efecto.

+0

¿Se acabó el tiempo para finalizar la operación? – mydogisbox

+0

@mydogisbox: Parece que. Sin embargo, no sé por qué. Parece que el comando de espera en Guardar() no espera hasta la creación sino que vuelve inmediatamente (o después de la creación del archivo) fuera de la función de guardar. Esto también es lo que veo, si agrego Debug.WriteLine-calls después de cada llamada a un método.Sin un punto de interrupción, el código nunca alcanzará la llamada "var xDox = GetXDocument()". Vuelve después de la creación del archivo (pero sin excepción). – HCL

Respuesta

7

El problema fue la llamada al método Guardar. Solo se esperaba la primera parte (creación del archivo), la segunda parte (guardar XML) se hizo de manera asíncrona y, por lo tanto, el aplazamiento de la operación de suspensión no ha sido hasta el final del proceso de guardado.

Una posible solución para evitar este problema es esperar explícitamente a que se complete la operación de salvar. Esto se puede lograr declarando el método OnSuspending como aysnc y luego esperando la finalización de la operación de guardar con la palabra clave await (tenga en cuenta el tipo de devolución de tarea del método Save).

private async void OnSuspending(object sender, SuspendingEventArgs e){       
    var deferral = e.SuspendingOperation.GetDeferral();      
    if (null != m_document) await Save(); 
    deferral.Complete(); 
} 

async Task Save(){ 
    var folder = KnownFolders.DocumentsLibrary;  
    var file = await folder.CreateFileAsync(GetFileName(),Windows.Storage.CreationCollisionOption.ReplaceExisting);     

    var xDoc = GetXDocument(); 
    using (var stream = await file.OpenStreamForWriteAsync()){ 
     xDoc.Save(stream);      
    }   
} 

Espero que este post ayuda a otra persona que se ha caído en la misma trampa (me pregunto por qué el problema no ha ocurrido con la beta de W8, pero creo que la EM ha optimizado la aplicación termination- proceso y, por lo tanto, hay menos tiempo para un trabajo inesperado después del proceso de suspensión) ...

+0

No olvides llamar 'diferir.Completo();' al final. – mydogisbox

+0

@mydogisbox: Gracias, pero "deferall.Commit()" siempre estuvo presente, observe la implementación de OnSuspending. Solo eliminé el try/finally para hacer el ejemplo más pequeño. El problema no era el completo, sino la serialización del XML. En mi rutina inicial (Guardar), no he comentado que el método se ejecutará parcialmente de forma asíncrona (ver el código después de "aguardar carpeta.Crear ..."). La solución fue esperar hasta la finalización de todo el método (ver la espera en OnSuspending y el tipo de devolución "Tarea" de Guardar()). – HCL

3

Se está quedando sin tiempo. Empiezas con aproximadamente 5 segundos, pero si no declaras que lo usarás, tu tiempo se verá truncado. Prueba esto:

private async void OnSuspending(object sender, SuspendingEventArgs e) 
{ 
    var deferral = e.SuspendingOperation.GetDeferral(); 
    try 
    { 
     await Task.Delay(1000); 
     Debug.WriteLine("Done"); 
    } 
    finally 
    { 
     deferral.Complete(); 
    } 
} 

Ver here para más detalles. Ver here para la documentación oficial:

Nota Si tiene que hacer un trabajo asíncrono cuando su aplicación está siendo suspendido tendrá que diferir la finalización de suspender hasta después su trabajo completa. Puede utilizar el método GetDeferral en el objeto SuspendingOperation (disponible a través de los argumentos del evento) para retrasar finalización de suspender hasta después de llamar al método Complete en el objeto SuspendingDeferral devuelto .

+0

¡Gracias por tu respuesta! Lamentablemente, no resuelve el problema. Si miras el ejemplo de mi código, ya difiero la suspensión, solo he eliminado todo el manejo de excepciones por simplicidad del ejemplo. Sin embargo, no hace diferencia. – HCL

+0

He encontrado el problema. Por favor, mira mi respuesta y gracias de nuevo por tu publicación. – HCL

+0

@HCL, la solución que di fue la que necesitabas ... Simplemente omití involuntariamente las dos partes clave ... Las vuelvo a poner ahora. – mydogisbox

Cuestiones relacionadas