Reputation: 19
I am making an application that will save a file from an array when the user exits. I have placed the following code at the bottom of the app.xaml.cs page where the exit event handler is normally, however, this code is not properly saving my file.
private async void OnSuspending(object sender, SuspendingEventArgs e)
{
await Closer();
var deferral = e.SuspendingOperation.GetDeferral();
//TODO: Save application state and stop any background activity
deferral.Complete();
}
private async Task Closer()
{
Windows.Storage.StorageFolder storageFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
Windows.Storage.StorageFile saver = await storageFolder.CreateFileAsync("scores.txt", Windows.Storage.CreationCollisionOption.ReplaceExisting);
var listOfStrings = new List<string> { Globals.scoreKeeper[0], Globals.scoreKeeper[1], Globals.scoreKeeper[2], Globals.scoreKeeper[3], Globals.scoreKeeper[4], Globals.scoreKeeper[5], Globals.scoreKeeper[6], Globals.scoreKeeper[7], Globals.scoreKeeper[8], Globals.scoreKeeper[9], Globals.scoreKeeper[10], Globals.scoreKeeper[11], Globals.scoreKeeper[12], Globals.scoreKeeper[13], Globals.scoreKeeper[14], Globals.scoreKeeper[15], Globals.scoreKeeper[16], Globals.scoreKeeper[17], Globals.scoreKeeper[18], Globals.scoreKeeper[19], Globals.scoreKeeper[20], Globals.scoreKeeper[21], Globals.scoreKeeper[22], Globals.scoreKeeper[23], Globals.scoreKeeper[24], Globals.scoreKeeper[25], Globals.scoreKeeper[26], Globals.scoreKeeper[27] };
await Windows.Storage.FileIO.AppendLinesAsync(saver, listOfStrings);
}
This same save system does work on other parts of the application, but it wipes the whole file every time I run it here. I have thoroughly searched both stackoverflow, and other programming help websites, but I have found no solution to this problem. If possible, I would appreciate a prompt response.
Thanks.
Upvotes: 1
Views: 96
Reputation: 21899
You need to get your deferral before awaiting Closer not after. The app continues suspending as soon as the OnSuspending returns at the first await, and since the deferral isn't active it doesn't wait for it:
var deferral = e.SuspendingOperation.GetDeferral();
//TODO: Save application state and stop any background activity
await Closer();
deferral.Complete();
See the Remarks in the Handle app suspend documentation, which say:
If you make an asynchronous call within your handler, control returns immediately from that asynchronous call.
That means that execution can then return from your event handler and your app will move to the next state even though the asynchronous call hasn't completed yet.
In your case, await Closer();
returns immediately, before the deferral is claimed, and the app continues to suspend without waiting for Closer to finish. Since it's wiping the file we know that Closer runs far enough to replace it, but not far enough to write out the new data. How far Closer gets is not deterministic though, and sometimes it may not get that far and sometimes it could get farther.
To ensure that it is deterministic and is waited for, it needs to run during the Deferral block, and if it may more than a few seconds to save you may need an ExtendedExecutionSession as well:
Use the GetDeferral method on the EnteredBackgroundEventArgs object that is passed to your event handler to delay suspension until after you call the Complete method on the returned Windows.Foundation.Deferral object.
A deferral doesn't increase the amount you have to run your code before your app is terminated. It only delays termination until either the deferral's Complete method is called, or the deadline passes-whichever comes first. To extend time in the Suspending state use ExtendedExecutionSession
Upvotes: 1