1

我正在编写一个 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 !!!!!");
        }

从未打印停用!

4

2 回答 2

7

问题出在await关键字上。简而言之,await实际上并没有像听起来那样阻塞正在执行的线程。恰恰相反,当执行到await关键字时,它看起来像return从调用者的角度来看。延续(await关键字之后的内容)计划稍后运行,当与之关联的任务await完成时。有关这方面的更多详细信息,我鼓励您阅读更多关于await和任务的信息,例如,从这里开始。

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

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

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

当控制离开 Application_Deactivated 时,您的应用程序被认为已准备好关闭。但实际上它还没有准备好,因为await writer.WriteAsync(data);可能还没有开始。这就是为什么您的应用程序在没有写入任何内容的情况下关闭的原因。

顺便说一句,如果您的应用在停用期间没有被墓碑化,就像您快速返回它一样,WriteAsync最终应该会完成。但是,这当然不是你所期望的。

为了解决这个问题,您需要同步运行文件写入操作。顺便说一句,这正是旧 API 所做的,这就是它起作用的原因。解决问题的最简单方法是将CacheData函数更改为 returnTask而不是void(to 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();
}
于 2013-02-18T13:09:59.320 回答
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();
}
于 2014-04-20T22:55:54.613 回答