Richard Mannion
Richard Mannion

Reputation: 289

Windows Phone 8 Hanging on GetFolderAsync and OpenStreamForReadAsync

I am making a windows phone 8 application. Part of this application requires state to be saved. I am saving it as a string of Json. If I open the application, save some data, exit the application and the load it again, it hangs on either GetFolderAsync or OpenStreamForReadAsync. It does not happen every time, but once it starts hanging, I have to kill the whole emulator and make a new one to start the application again.

I have even tried just making an empty file with no data in it and the problem still persistes.

Below is the code I am using to save and load the data. It does not matter where I call the data load whether it be on application start or on the form load it still breaks.

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

        }
    }

Upvotes: 2

Views: 1206

Answers (1)

Stephen Cleary
Stephen Cleary

Reputation: 456457

You are causing a deadlock by calling Result. I explain this deadlock on my blog and in a recent MSDN article. In summary, await will (by default) attempt to resume execution within a context (the current SynchronizationContext unless it is null, in which case it uses the current TaskScheduler).

In your case, the current SynchronizationContext is the UI context, which is only used by the UI thread. So when you block the UI thread by calling Result, the async method cannot schedule back to the UI thread to complete.

Upvotes: 2

Related Questions