问题
For a Windows 8 Application in C/XAML I have to store some data to the LocalState folder. I have some trouble using async/await operator I think.
When I am saving datas while the application is running, everything works fine, but when I try to save the data during the OnSuspending method, it seems that my application doesn't wait for my saving method to be finished to suspend the application.
The stranger thing is that when I'm debugging and doing all the operation step by step slowly everything works fine, but when I don't put any breakpoints, the application is closed before the data are saved.
Here is my code :
private async void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
await api.BeforeClosing(true);
deferral.Complete();
}
public async Task BeforeClosing(Boolean toTombstoning)
{
SaveItem<LoadingProgress>(fileNameLoadingProgress, InitLoading);
}
public static async void SaveItem<T>(String fileName, T data, Boolean crossThreadSecure = false) where T : IBinarySerializable
{
await CreateNewStorageFile(fileName);
StorageFolder localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
StorageFolder dataFolder = await localFolder.GetFolderAsync("Data");
StorageFile file = await dataFolder.GetFileAsync(fileName);
using (var stream = await file.OpenStreamForWriteAsync())
{
using (var writer = new BinaryWriter(stream))
{
writer.Write<T>(data);
}
}
}
public async static Task CreateNewStorageFile(string filename)
{
StorageFolder localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
StorageFolder dataFolder = await localFolder.CreateFolderAsync("Data", CreationCollisionOption.OpenIfExists);
storage = await dataFolder.CreateFileAsync(filename, CreationCollisionOption.OpenIfExists);
}
Am I doing something wrong with the await operator? Or is there a maximum amount of time when we can do some operations before suspending the application?
Thank you
EDIT : I made some new tests : If I remove deferral.Complete(); from the OnSuspending method, it saves the data well (but never close the app obviously...). I really think the problem is that I run out of time when the application is suspending. It really looks like the problem on this thread : StorageFolder.CreateFileAsync crashes when called from App.OnSuspending. But I have tried all the solutions of this question and I still have the problem...
回答1:
Your problem is that you're calling Complete
before all your async
operations have completed.
The simplest solution is to make SaveItem
an async Task
method instead of async void
, and then await
it in BeforeClosing
.
As a general rule, async
methods should always return Task
/Task<T>
unless they have to return void
(e.g., event handlers).
回答2:
The short and surprising answer is that OnSuspending is an unreliable place for any application critical persistence logic. For some reason Microsoft made the decision to delay the OnSuspending event for 5-10 seconds after an application has been closed. If the application is re-launched prior to this event a separate instance of the application is spawned and it is unaware of the one that is still in the process of suspending.
I came to this conclusion after having problems following what seemed like very simple examples in the WinRT Application Data Sample project: http://code.msdn.microsoft.com/windowsapps/ApplicationData-sample-fb043eb2. After some frustration I found a thread on MSDN that discusses OnSuspending as a trigger for saving: http://social.msdn.microsoft.com/Forums/en-US/winappswithcsharp/thread/43da2212-9910-461d-816a-94b479ce9885/. The gist of this thread is that you should save as often and frequently as possible because OnSuspending is unreliable.
来源:https://stackoverflow.com/questions/12212831/saving-data-during-the-onsuspending-method