locked
Saving the application data to file in the Application.OnSuspending method does not work?

    Question

  • I a using this code to save the application's data model to file:

            async void OnSuspending(object sender, SuspendingEventArgs e)
            {
                SuspendingDeferral deferral = e.SuspendingOperation.GetDeferral();
    
    
                // Will contain the application data
                string applicationData = "";
                string filename = "model.xml";
    
                XmlSerializer serializer = new XmlSerializer(typeof(Model.Model));
                StringWriter stringWriter = new StringWriter();
                serializer.Serialize(stringWriter, (Application.Current as App).ApplicationModel);
                applicationData = stringWriter.ToString();
                
    
                // Now write to file
                StorageFile file = await ApplicationData.Current.LocalFolder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);
                await FileIO.WriteTextAsync(file, applicationData);
    
                deferral.Complete();
            }

    This does work well if I trigger the Suspension via Visual Studio or if I trigger the Suspension and Termination via Visual Studio.

    But: It does not work, if I manually Close the application (Alt+F4). That's driving me crazy, I don't seem capable of finding the solution for this (maybe simple) problem!!

    Saturday, March 31, 2012 12:24 AM

Answers

  • Please don't bump posts from previous versions. This is a very good way for your comments to be missed or ignored. There are other more recent threads on this topic.

    To summarize, if the user closes the app and then immediately restarts before the first instance has finished closing then the first instance is forcibly terminated so the user runs in a clean state. If this occurs before the first instance had suspended then that event won't be triggered.

    The general solution is as Andrei mentioned: checkpoint important data earlier and more frequently. VisibilityChanged is often a reasonable location.

    Use the Suspending to save state about where in the app the user is rather than actual data.

    --Rob

    Thursday, November 08, 2012 2:05 AM
    Owner
  • You should not use Suspending event handler as the main place to save your data.

    There are many reasons for not doing this and the first of them you found by yourself. The other reason is a limited time your app can stay in suspending state - allowed 5 seconds may be not enough to store all your data. So save your data regularly and often while your app is running and think about Suspending event as a last chance to store just modified data.

    Saturday, May 05, 2012 10:28 AM

All replies

  • It works quite fine for me, event hits breakpoint on OnSuspending when you manually close the application.

    Try uninstalling it and starting again.

    - ngm

    Saturday, March 31, 2012 5:07 AM
  • Thank you for your answer, but after reinstalling it doesn't work eiter.

    Even if I write key / value pairs to the local application setttings, they're not saved.

    It seems to me that the Application.OnSuspending Method does not get called when I Close the application manually.

    Everything works fine if I trigger the Suspension / Termination inside the Visual Studio.

    Maybe this is a bug?

    Saturday, March 31, 2012 2:32 PM
  • ehssandoust,

    I tried with deferral and it works too.

    Please note that it takes few seconds for OnSuspending to get called after the application is closed by user manually. Clicking on "Suspend the application" in VS will have OnSuspending called almost instantly.

    Try removing your logic in OnSuspending and both putting the break point and/or System.Diagnostics.Debug.WriteLine() to trace the call.

    Make sure to eliminate persistence logic and confirm whether OnSuspending gets called.

    It really invokes the method if the user manually close the app by dragging it to the bottom of the screen or via Alt+F4 shortcut.

    - ngm


    • Edited by ngmO11 Saturday, March 31, 2012 7:06 PM Being more explicit.
    Saturday, March 31, 2012 6:47 PM
  • ngmO11, Thank you very much!

    As you said, I realized now, that I have to wait ~10sec before I can reopen the app - the OnSuspended method call comes in with delay.

    Yet this does not fully solve my problem. If I close the app and reopen it before the Application.OnSuspended method gets called, this will result in a data loss.

    In that case the args.PreviousExecutionState in the Application.OnLaunched-method is set to NotRunning, even though the app is technically still running, because the OnSuspended method has not been called yet.

    As you can see here (http://msdn.microsoft.com/en-us/library/windows/apps/hh464925.aspx, first image on the site), the application should always be suspended BEFORE it enters the NotRunning state.

    What is the best (recommended) practice to prevent such a data loss?



    • Edited by xact91 Saturday, March 31, 2012 9:38 PM
    Saturday, March 31, 2012 9:34 PM
  • ehssandoust,

    You're right, if user closes application and then immediately opens it again so that it's opened before OnSuspended is called, she's going to get the new application instance where OnSuspended won't be invoked on previous instance:

    1 - Instance A -> OnLaunched

    2 - User closes application manually

    3 - User opens the same application within <4 seconds by clicking on the title

    4 - Instance B -> OnLaunched

    (application works in the background for some time)

    5 - Instance B -> OnSuspending

    6 - Instance B -> OnSuspending

    7 - User closes application manually

    8 - User opens the same application within <4 seconds by clicking on the title

    9 - Instance C -> OnLaunched

    Steps #5 and #6 are saying that if the application is left working in background for some time, runtime will call OnSuspending even though it's not going to terminate it. That's the sweet spot for you to do the state persistence. However, according to this trace dump, it's obvious that you can have dirty state (between steps #6 and #7) and still unable to save it if the user do this "fast closing / reopening".

    This doesn't sound consistent at all.

    -ngm

    Sunday, April 01, 2012 1:05 AM
  • ngmO11,

    So this is an issue and hopefully will be resolved?

    Yury

    Wednesday, April 25, 2012 10:41 AM
  • I use Suspending event to store app data.

    But if I close the app (by gesture or alt-f4) and reopen it before the Application.OnSuspended method gets called, this will result in a data loss.

    App state is NotRunning.

    See http://social.msdn.microsoft.com/Forums/en-SG/winappswithcsharp/thread/43da2212-9910-461d-816a-94b479ce9885

    Do you have an example how to avoid such data loss?

    Regards,

    Yury

    Saturday, May 05, 2012 6:17 AM
  • You should not use Suspending event handler as the main place to save your data.

    There are many reasons for not doing this and the first of them you found by yourself. The other reason is a limited time your app can stay in suspending state - allowed 5 seconds may be not enough to store all your data. So save your data regularly and often while your app is running and think about Suspending event as a last chance to store just modified data.

    Saturday, May 05, 2012 10:28 AM
  • You should not use Suspending event handler as the main place to save your data.

    There are many reasons for not doing this and the first of them you found by yourself. The other reason is a limited time your app can stay in suspending state - allowed 5 seconds may be not enough to store all your data. So save your data regularly and often while your app is running and think about Suspending event as a last chance to store just modified data.

    I dont find Above Solution as Attractive...still I think currently we have only this solution as suggested by Andrei Marukovich. (Thanks)

    But what If I want to remember all kind of settings Say Radio button Status, or Search string in Text box or Last selected thing in my list view etc...say as a Key Value pair ...

    If I do it everytime...application performance may get affected...also each Control's event handler must be handled (Text changed event for Text box etc)....

    Monday, May 28, 2012 6:54 AM
  • I use Suspending event to store app data.

    But if I close the app (by gesture or alt-f4) and reopen it before the Application.OnSuspended method gets called, this will result in a data loss.

    App state is NotRunning.

    See http://social.msdn.microsoft.com/Forums/en-SG/winappswithcsharp/thread/43da2212-9910-461d-816a-94b479ce9885

    Do you have an example how to avoid such data loss?

    Regards,

    Yury

    Anybody from Microsoft have better solution for the same problem ?

    Mr. Rob Caplan..Can you please help.

    I want to port existing application in Windows7 as a Metrostyle appli. which needs to save some stuff as soon as appli is closed (In order to view to appli as user opens again in the same state..). Currently I am using Suspended event handler..but because of the 10 SEC delay..I am getting trouble. Is there any event Equivalent to past windows appli event OnClosing etc..

    Monday, May 28, 2012 6:58 AM
  • Bumping to see if anyone has updates.
    Tuesday, July 24, 2012 11:36 PM
  • No updates but the same Problem and also interested in a solution :-/
    Wednesday, July 25, 2012 3:47 PM
  • Is suspend never called on the first instance?

    If it is eventually called, you could wait on a Mutex in the new instance, showing a message to the user while blocked indicating it's waiting for the data from a previous instance.


    Anthony Wieser | Wieser Software Ltd | www.wieser-software.com

    Saturday, August 25, 2012 7:05 AM
  • never called.

    I have to use Window.Current.VisibilityChanged event to store the data...

    Tuesday, October 09, 2012 8:08 AM
  • If OnSuspending event is not a good place to store the data (since it is not guarantee to be invoked) then why I see TODO: comment " Save application state" when create new project?

            private void OnSuspending(object sender, SuspendingEventArgs e)
            {
                var deferral = e.SuspendingOperation.GetDeferral();
                //TODO: Save application state and stop any background activity
                deferral.Complete();
            }

    Tuesday, October 09, 2012 8:40 AM
  • I just want to let Microsoft know that the decision to delay the Suspend event is totally moronic. "5 seconds may not be enough for my app to save the state"? Well how do you know? I know this, you don't! Did you experience problems with the Deactivated event in Windows Phone that you decided to fix something that was not broken? I am not doing anything to fix my app in the case where the user opens it before Suspend is fired he will just lose data. I doubt the app will be rejected for this either since I am sure most 99% of the apps that store data will fail this test and also looking at the apps available for Windows 8 right now you are desparate and will accept just about anything.

    Fear is the mind-killer!

    Wednesday, November 07, 2012 3:27 PM
  • Please don't bump posts from previous versions. This is a very good way for your comments to be missed or ignored. There are other more recent threads on this topic.

    To summarize, if the user closes the app and then immediately restarts before the first instance has finished closing then the first instance is forcibly terminated so the user runs in a clean state. If this occurs before the first instance had suspended then that event won't be triggered.

    The general solution is as Andrei mentioned: checkpoint important data earlier and more frequently. VisibilityChanged is often a reasonable location.

    Use the Suspending to save state about where in the app the user is rather than actual data.

    --Rob

    Thursday, November 08, 2012 2:05 AM
    Owner
  • Where do you suggest this discussion be continued Rob?

    I'm concerned that there is nowhere safe to save your data, as no matter what if you have any async operations (and you will, as you're saving to a file) you could be terminated.

    You said above:

    "To summarize, if the user closes the app and then immediately restarts before the first instance has finished closing then the first instance is forcibly terminated "

    Imagine I'm trying to save data in response to the VisibilityChanged event, and I have a semaphore that I hold while I haven't yet completed the save.

    If I block on that semaphore during my Suspending notification, I'll get terminated.  If I don't block on that semaphore, I'll also be terminated.  If there's no way to prevent the termination, I can't see any way that you can reliably save data on the platform, which means unhappy customers and low sales in the end.


    Anthony Wieser | Wieser Software Ltd | www.wieser-software.com

    Sunday, November 11, 2012 7:35 AM