3

对于 C/XAML 中的 Windows 8 应用程序,我必须将一些数据存储到 LocalState 文件夹。我认为我在使用 async/await 运算符时遇到了一些麻烦。

当我在应用程序运行时保存数据时,一切正常,但是当我尝试在 OnSuspending 方法期间保存数据时,我的应用程序似乎没有等待我的保存方法完成以暂停应用程序。

奇怪的是,当我在调试并逐步进行所有操作时,一切正常,但是当我不放置任何断点时,应用程序在保存数据之前就关闭了。

这是我的代码:

    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);
    }

我对 await 运算符做错了吗?或者在暂停应用程序之前我们可以做一些操作的最大时间量是多少?

谢谢

编辑:我做了一些新的测试:如果我删除 deferral.Complete(); 从 OnSuspending 方法来看,它可以很好地保存数据(但永远不要关闭应用程序......)。我真的认为问题在于应用程序暂停时我的时间用完了。看起来确实像这个线程上的问题:StorageFolder.CreateFileAsync 在从 App.OnSuspending 调用时崩溃。但是我已经尝试了这个问题的所有解决方案,但我仍然有问题......

4

2 回答 2

10

您的问题是您Complete在所有async操作完成之前打电话。

最简单的解决方案是制作SaveItem一个async Task方法而不是async void,然后awaitBeforeClosing.

作为一般规则,async方法应该总是返回Task/Task<T>除非它们必须返回void(例如,事件处理程序)。

于 2012-08-31T11:04:57.920 回答
7

简短而令人惊讶的答案是 OnSuspending 对于任何应用程序关键的持久性逻辑来说都是一个不可靠的地方。出于某种原因,Microsoft 决定在应用程序关闭后将 OnSuspending 事件延迟 5-10 秒。如果应用程序在此事件之前重新启动,则会生成一个单独的应用程序实例,并且它不知道仍在暂停过程中的应用程序实例。

在遵循 WinRT 应用程序数据示例项目中看似非常简单的示例后,我得出了这个结论:http: //code.msdn.microsoft.com/windowsapps/ApplicationData-sample-fb043eb2。经过一番挫折后,我在 MSDN 上找到了一个讨论 OnSuspending 作为保存触发器的线程:http: //social.msdn.microsoft.com/Forums/en-US/winappswithcsharp/thread/43da2212-9910-461d-816a-94b479ce9885/ . 该线程的要点是您应该尽可能频繁地保存,因为 OnSuspending 是不可靠的。

于 2013-01-22T17:06:52.043 回答