【问题标题】:Windows Phone 8 Hanging on GetFolderAsync and OpenStreamForReadAsyncWindows Phone 8 挂在 GetFolderAsync 和 OpenStreamForReadAsync 上
【发布时间】:2013-06-08 14:21:11
【问题描述】:

我正在制作一个 windows phone 8 应用程序。此应用程序的一部分需要保存状态。我将它保存为一串Json。如果我打开应用程序,保存一些数据,退出应用程序并再次加载它,它会挂在 GetFolderAsync 或 OpenStreamForReadAsync 上。不是每次都这样,但是一旦开始挂起,我必须杀死整个模拟器并创建一个新的模拟器才能再次启动应用程序。

我什至尝试过创建一个没有数据的空文件,但问题仍然存在。

下面是我用来保存和加载数据的代码。不管我在哪里调用数据加载,无论是在应用程序启动时还是在表单加载时,它仍然会中断。

    private async Task SaveLists()
    {
        //XmlSerializer serializer = new XmlSerializer(typeof(ListHolder));

        // Get the local folder.
        StorageFolder local = Windows.Storage.ApplicationData.Current.LocalFolder;

        // Create a new folder name DataFolder.
        var dataFolder = await local.CreateFolderAsync("DataFolder",
            CreationCollisionOption.OpenIfExists);

        // Create a new file named DataFile.txt.
        var file = await dataFolder.CreateFileAsync("Lists.json",
        CreationCollisionOption.ReplaceExisting);

        string json = JsonConvert.SerializeObject(Lists, Formatting.Indented);
        byte[] fileBytes = System.Text.Encoding.UTF8.GetBytes(json.ToCharArray());

        using (var s = await file.OpenStreamForWriteAsync())
        {
            s.Write(fileBytes, 0, fileBytes.Length);

        }
    }



    private async Task LoadLists()
    {


        // Get the local folder.
        StorageFolder local = Windows.Storage.ApplicationData.Current.LocalFolder;

        if (local != null)
        {
            try
            {
                // Get the DataFolder folder.

                var dataFolder = await local.GetFolderAsync("DataFolder");

                // Get the file.
                var files = dataFolder.GetFilesAsync();
                var file = await dataFolder.OpenStreamForReadAsync("Lists.json");

                string jsonString = "";
                // Read the data.
                using (StreamReader streamReader = new StreamReader(file))
                {
                    jsonString = streamReader.ReadToEnd();
                }
                if (jsonString.Length > 0)
                {
                    Lists = JsonConvert.DeserializeObject<List<ItemList>>(jsonString);
                }    
                else
                {
                    Lists = new List<ItemList>();
                }                
            }
            catch (Exception ex)
            {
                Lists = new List<ItemList>();
            }

        }
    }

【问题讨论】:

  • 您是否检查过该文件夹是否真的存在并包含您希望它包含的数据? (我的意思是,手动,而不是编程。)
  • @Richard - 你如何调用你的函数? 1) await LoadLists(), 或 2) LoadLists().Wait()?
  • 我调用的是这样的:await LoadLists();
  • 不幸的是,我看不到文件夹和文件是否真的存在,因为它们作为应用程序的一部分在手机上。有没有办法在没有代码的情况下实际看到它们?我确实调用了 GetFoldersAsync,我可以在 Quickwatch 窗口中看到该文件夹​​
  • @RichardMannion:你的调用堆栈中有WaitResult anywhere 吗?或者这一切都是从 async void 事件处理程序开始的?

标签: asynchronous windows-phone-8 io


【解决方案1】:

您通过调用Result 导致了死锁。我解释了这个僵局on my blogin a recent MSDN article。总之,await 将(默认情况下)尝试在上下文中恢复执行(当前的SynchronizationContext,除非它是null,在这种情况下它使用当前的TaskScheduler)。

在您的情况下,当前 SynchronizationContext 是 UI 上下文,仅由 UI 线程使用。所以当你通过调用Result阻塞UI线程时,async方法不能调度回UI线程来完成。

【讨论】:

  • 谢谢。这似乎解决了问题。在加载数据和实际加载 GUI 之间仍然存在时间问题,但这应该是可以解决的。我会读你的博客谢谢。
  • 为此,我建议您有目的地为您的 UI 设计一个“加载”状态,让您的初始加载在该状态下开始,并在数据加载时转换状态。如果你使用 MVVM,我写了一个NotifyTaskCompletion type,它本质上允许你将数据绑定到Task 结果(并在Task 完成时获得INotifyPropertyChanged 事件)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多