Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WinRT: Loading static data with GetFileFromApplicationUriAsync()

I have some data in my windows 8 application which should be shipped with and is just some static data. In fact: It's a simple xml file which should get deserialized.

The data is saved in Assets\data.xml (Assets is the default folder from the Blank App Template).

I'm using this piece of code to access it:

private static async Task<MyObject> Load()
{
    if (Windows.ApplicationModel.DesignMode.DesignModeEnabled)
    {
        return new SampleData();
    }

    var uri = new Uri("ms-appx:///Assets/data.xml");
    Debug.WriteLine("Getting file from Application");
    var file = await StorageFile.GetFileFromApplicationUriAsync(uri);
    Debug.WriteLine("Opening file for reading async");
    var stream = await file.OpenStreamForReadAsync();

    var serializer = new XmlSerializer(typeof(MyObject));

    Debug.WriteLine("Begin deserialization");
    var result = (MyObject)serializer.Deserialize(stream.AsInputStream().AsStreamForRead());

    return result;
}

Calling method:

public static MyObject GetMyObject()
{
    if (_myObject == null)
    {
        _myObject = Load().Result;
    }

    return _myObject;
}

The "funny" part about that is:

If I set a breakpoint at var uri = new Uri(...); and use F11 to step through the code, everything works as expected. I get all of the debug lines and my Application shows the static data as wanted.

If I don't set a breakpoint and don't step over this piece of code, I only get the Debug output of Getting a file from Application and nothing more happens. It seems that GetFileFromApplicationUriAsync() never comes back. I waited more than five minutes but still nothing happend.

Anyone got any idea?

like image 601
Manuel Rauber Avatar asked Sep 02 '12 10:09

Manuel Rauber


1 Answers

Thanks for posting code. Please try to change your method Load as the following:

//your code
var file = await StorageFile.GetFileFromApplicationUriAsync(uri).AsTask().ConfigureAwait(false);
//your code
var stream = await file.OpenStreamForReadAsync().ConfigureAwait(false);
//your code

The main difference here is AsTask().ConfigureAwait(false)

EDIT:

Good to hear that it's working. Explanation is quite simple: when you use task.Result or task.Wait() on GUI thread in conjunction with await keyword you're causing deadlock. This happens because after awaiting code is resumed on the same context it was invoked (in your case - GUI thread). And because GUI thread currently waiting for task to complete (via Result or Wait()) deadlock arises and code after await keyword will never be invoked. ConfigureAwait(false) specifies that current context can be ignored and thus allows your code to complete successfully. More details on this here: http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html

like image 196
Alexander Avatar answered Nov 15 '22 05:11

Alexander