在停用应用时,无法将数据保存到StorageFile

时间:2013-02-18 12:25:49

标签: windows-phone-8 isolatedstorage winrt-async storagefile

我正在编写一个WP8应用程序,并希望在停用或关闭应用程序时保存一些数据。

我尝试过新的WinRT API,但在停用应用时无法正常工作:|

代码:

 public async Task CacheData()
        {

            StorageFolder localFolder = ApplicationData.Current.LocalFolder;

                string data = "Hello!";

                ///WinRT not Working !!!

                // Get a reference to the Local Folder 
                // Create the file in the local folder, or if it already exists, just replace it 

                StorageFile storageFileIsolated = await localFolder.CreateFileAsync("Data.data", CreationCollisionOption.ReplaceExisting);
                Stream writeStream = await storageFileIsolated.OpenStreamForWriteAsync();
                using (StreamWriter writer = new StreamWriter(writeStream))
                {
                    await writer.WriteAsync(data);
                }
            }
        }

但与旧api一起正常工作

                string data = "Hello!";

                using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    using (IsolatedStorageFileStream rawStream = isf.CreateFile("Data.store"))
                    {
                        StreamWriter writer = new StreamWriter(rawStream);
                        writer.WriteLine(data); // save the message
                        writer.Close();
                    }
                }

我不知道问题是什么:| !!!

我用这段代码测试了它

 private  void Application_Deactivated(object sender, DeactivatedEventArgs e)
        {
            ViewModel.CacheExchangeRates().Wait();
            System.Diagnostics.Debug.WriteLine("deactivated !!!!!");
        }

从未打印停用!!!

2 个答案:

答案 0 :(得分:7)

问题在于await关键字。简而言之,await确实不会阻止执行线程,因为它可能听起来。恰恰相反,当执行到await关键字时,从调用者的角度来看,它看起来像return。与await关联的任务完成后,计划在稍后运行继续(await关键字之后)。有关详细信息,建议您详细了解await和任务,例如here

在您的情况下,当调用Deactivated或Closing时,您可能会拨打类似于:

的电话
private void Application_Deactivated(object sender, DeactivatedEventArgs e)
{
    CacheData();
}

当执行第一个await关键字(即行StorageFile storageFileIsolated = await localFolder.CreateFileAsync("Data.data", CreationCollisionOption.ReplaceExisting);)时,您的CacheData()方法会将控制权返回给调用者。当该任务完成时,其他所有内容都将在稍后运行。但是你并没有在Application_Deactivated方法中等待它。相反,执行继续,控制离开Application_Deactivated

当控件离开Application_Deactivated时,您的应用程序将被视为已准备好关闭。但实际上还没准备好,因为await writer.WriteAsync(data);可能还没有开始。这就是为什么你的应用程序关闭而不写任何东西。

顺便说一句,如果您的应用在停用期间没有进行逻辑删除,就像您快速返回它一样,WriteAsync最终应该完成。但当然这不是你所期望的。

为了解决这个问题,您需要同步运行文件写操作。顺便说一句,这正是旧API所做的,这就是它的工作原理。解决问题的最简单方法是将CacheData函数更改为Task而不是void(至public async Task CacheData()),并在您的Task.Wait()中使用Application_Deactivated public async Task CacheData() { StorageFolder localFolder = ApplicationData.Current.LocalFolder; string data = "Hello!"; ///WinRT not Working !!! // Get a reference to the Local Folder // Create the file in the local folder, or if it already exists, just replace it StorageFile storageFileIsolated = await localFolder.CreateFileAsync("Data.data", CreationCollisionOption.ReplaceExisting); Stream writeStream = await storageFileIsolated.OpenStreamForWriteAsync(); using (StreamWriter writer = new StreamWriter(writeStream)) { await writer.WriteAsync(data); } } private void Application_Deactivated(object sender, DeactivatedEventArgs e) { CacheData().Wait(); } 处理程序。像这样:

{{1}}

答案 1 :(得分:2)

我遇到了同样的问题,将其修复为

StorageFile storageFileIsolated = localFolder.CreateFileAsync("Data.data", CreationCollisionOption.ReplaceExisting).AsTask().Result;
Stream writeStream = storageFileIsolated.OpenStreamForWriteAsync().Result;
using (StreamWriter writer = new StreamWriter(writeStream))
{
    writer.WriteAsync(data).Wait();
}