visual una tutorial studio que plataforma for create app c# win-universal-app windows-10-mobile

c# - una - uwp windows 7



¿Ejecución extendida no funciona correctamente? (2)

El uso de la await y la Task está haciendo que su tarea continuada permanezca en el hilo principal, por lo que tiene que esperar con la pantalla negra. Recuerde que el comportamiento de await es programar la ejecución en el Dispatcher , NO para comenzar un nuevo hilo, NOR programar su ejecución en el ThreadPool. Como consecuencia, no se pueden procesar más mensajes de UI hasta que finalice el Delay() .

Simplemente realice la operación que consume tiempo en un nuevo hilo, pero asegúrese de mantener la sesión abierta hasta que finalice.

Eche un vistazo a este https://msdn.microsoft.com/en-us/magazine/jj991977.aspx para obtener una buena idea de cómo se programa la ejecución

No puedo hacer que ExtendedExecution funcione correctamente. El problema es que el evento Revoked no se activa hasta que finaliza la ejecución. Si tomamos una muestra:

private async void OnSuspending(object sender, SuspendingEventArgs e) { Debug.WriteLine("Suspending in app"); var deferral = e.SuspendingOperation.GetDeferral(); using (var session = new ExtendedExecutionSession()) { session.Reason = ExtendedExecutionReason.SavingData; session.Description = "Upload Data"; session.Revoked += (s, a) => { Debug.WriteLine($"Extended execution revoked because of {a.Reason}"); }; var result = await session.RequestExtensionAsync(); if (result == ExtendedExecutionResult.Denied) Debug.WriteLine("Extended execution failed"); else { Debug.WriteLine("Executing"); await Task.Run(() => { Task.Delay(9000).Wait(); Debug.WriteLine("Finished the task"); }); Debug.WriteLine("Executing finished"); } Debug.WriteLine("Suspending after execution"); } deferral.Complete(); }

La documentación indica que el evento Revoked debe activarse al reanudar la aplicación, pero si prueba el código con el depurador adjunto, verá que el resultado de la depuración parece estar bien, pero debe esperar 9000 ms para que se muestre. Esto significa que el código se suspende hasta que finaliza la sesión.

El mayor problema es que si lo disparas sin un depurador adjunto, inicias la aplicación, suspendes y luego reanudas, verás una pantalla en negro durante unos segundos y luego el sistema operativo terminará tu aplicación.

¿Me estoy perdiendo de algo? ¿Alguien lo tiene funcionando correctamente?


No hay problema de UI ni nada. Tu código funciona. Su expectativa es incorrecta.

Con la ExtendedExecutionSession le está diciendo a su aplicación que necesita tiempo para guardar y no se le revocará hasta que haya terminado. En tu caso eso lleva unos 9 segundos.

Intente suspender la aplicación, espere 10 segundos y luego revóquela. Sucederá de inmediato. Luego intente suspender la aplicación y revóquela antes de que finalice la sesión. Ahora, ExtendedExecutionSession le informará a su sistema operativo que su aplicación aún no se puede revocar y que tiene que esperar hasta que finalice el proceso de guardado. Eso es lo que quieres.

Ver documento de Microsoft sobre ejecución extendida :

La solicitud de una sesión de ejecución extendida ExtendedExecutionReason.SavingData mientras la aplicación se encuentra en estado de suspensión crea un problema potencial que debe tener en cuenta. Si se solicita una sesión de ejecución extendida mientras se encuentra en el estado Suspender, y el usuario solicita que la aplicación se inicie nuevamente, puede parecer que demora mucho en iniciarse. Esto se debe a que el período de tiempo de la sesión de ejecución extendida debe completarse antes de que se pueda cerrar la instancia anterior de la aplicación y se pueda iniciar una nueva instancia de la aplicación. El tiempo de ejecución del lanzamiento se sacrifica para garantizar que el estado del usuario no se pierda.

Lo que se menciona en la sección sobre "Revocar" también es interesante para usted:

Cuando el evento Revoked se activa para una sesión de ejecución extendida ExtendedExecutionReason.SavingData , la aplicación tiene un segundo para completar la operación que estaba realizando y finalizar la suspensión.

Un segundo no es suficiente para terminar tus 9 segundos de espera.

Para eliminar la posibilidad de demorar la visualización de su salida de depuración, puede probarla agregando la hora actual a la salida. El sistema operativo probablemente tiene un problema con la sesión que no se cierra correctamente porque los 9 segundos no terminan.

También tenga en cuenta el comentario en EnterBackground :

Anteriormente, su devolución de llamada suspendida era el mejor lugar para guardar el estado después de que un usuario terminara una sesión con su aplicación. Sin embargo, ahora una aplicación puede continuar ejecutándose en segundo plano y luego volver al primer plano debido a la actividad de activación sin llegar nunca al estado suspendido. El mejor lugar para guardar datos después de una sesión de usuario es en su controlador de eventos de fondo ingresado.

Probablemente querrá hacer su código en caso de que se Exiting evento Exiting .

Para OnSuspending intente hacer la espera con un bucle for que se interrumpe (cancelando el proceso de guardado) tan pronto como ocurre la revocación, solo esperando medio segundo a la vez.

ACTUALIZAR:

... O use una tarea en segundo plano , ya que la suspensión parece ser la única advertencia confiable antes de la terminación:

// // Declare that your background task''s Run method makes asynchronous calls by // using the async keyword. // public async void Run(IBackgroundTaskInstance taskInstance) { // // Create the deferral by requesting it from the task instance. // BackgroundTaskDeferral deferral = taskInstance.GetDeferral(); // // Call asynchronous method(s) using the await keyword. // var result = await ExampleMethodAsync(); // // Once the asynchronous method(s) are done, close the deferral. // deferral.Complete(); }

ACTUALIZACIÓN2 :

Para ver la forma "adecuada" de cómo se debe hacer, vea el ejemplo oficial :

private async void OnSuspending(object sender, SuspendingEventArgs args) { suspendDeferral = args.SuspendingOperation.GetDeferral(); rootPage.NotifyUser("", NotifyType.StatusMessage); using (var session = new ExtendedExecutionSession()) { session.Reason = ExtendedExecutionReason.SavingData; session.Description = "Pretending to save data to slow storage."; session.Revoked += ExtendedExecutionSessionRevoked; ExtendedExecutionResult result = await session.RequestExtensionAsync(); switch (result) { case ExtendedExecutionResult.Allowed: // We can perform a longer save operation (e.g., upload to the cloud). try { MainPage.DisplayToast("Performing a long save operation."); cancellationTokenSource = new CancellationTokenSource(); await Task.Delay(TimeSpan.FromSeconds(10), cancellationTokenSource.Token); MainPage.DisplayToast("Still saving."); await Task.Delay(TimeSpan.FromSeconds(10), cancellationTokenSource.Token); MainPage.DisplayToast("Long save complete."); } catch (TaskCanceledException) { } break; default: case ExtendedExecutionResult.Denied: // We must perform a fast save operation. MainPage.DisplayToast("Performing a fast save operation."); await Task.Delay(TimeSpan.FromSeconds(1)); MainPage.DisplayToast("Fast save complete."); break; } session.Revoked -= ExtendedExecutionSessionRevoked; } suspendDeferral?.Complete(); suspendDeferral = null; } private async void ExtendedExecutionSessionRevoked(object sender, ExtendedExecutionRevokedEventArgs args) { //If session is revoked, make the OnSuspending event handler stop or the application will be terminated if (cancellationTokenSource != null){ cancellationTokenSource.Cancel(); } await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { switch (args.Reason) { case ExtendedExecutionRevokedReason.Resumed: // A resumed app has returned to the foreground rootPage.NotifyUser("Extended execution revoked due to returning to foreground.", NotifyType.StatusMessage); break; case ExtendedExecutionRevokedReason.SystemPolicy: //An app can be in the foreground or background when a revocation due to system policy occurs MainPage.DisplayToast("Extended execution revoked due to system policy."); rootPage.NotifyUser("Extended execution revoked due to system policy.", NotifyType.StatusMessage); break; } suspendDeferral?.Complete(); suspendDeferral = null; }); }