【问题标题】:WinRT: Loading static data with GetFileFromApplicationUriAsync()WinRT:使用 GetFileFromApplicationUriAsync() 加载静态数据
【发布时间】:2025-12-07 11:35:01
【问题描述】:

我的 Windows 8 应用程序中有一些数据,这些数据应该是附带的,只是一些静态数据。事实上:这是一个简单的 xml 文件,应该反序列化。

数据保存在 Assets\data.xml 中(Assets 是空白应用模板中的默认文件夹)。

我正在使用这段代码来访问它:

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

调用方法:

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

    return _myObject;
}

“有趣”的部分是:

如果我在 var uri = new Uri(...); 处设置断点并使用 F11 单步执行代码,一切都会按预期进行。我得到了所有的调试行,我的应用程序根据需要显示了静态数据。

如果我不设置断点并且不跳过这段代码,我只会得到Getting a file from Application 的调试输出,并且不会再发生任何事情。似乎GetFileFromApplicationUriAsync() 再也不会回来了。我等了五分钟多,但仍然没有任何反应。

有人知道吗?

【问题讨论】:

  • 你能再贴一些源代码吗?特别是,请发布上述代码中的整个方法以及如何调用该方法的示例。

标签: c# asynchronous windows-8 windows-runtime winrt-xaml


【解决方案1】:

感谢您发布代码。请尝试更改您的方法Load 如下:

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

这里的主要区别是 AsTask().ConfigureAwait(false)

编辑:

很高兴听到它正在工作。解释很简单:当您在 GUI 线程上使用 task.Resulttask.Wait() 并结合 await 关键字时,您会导致死锁。发生这种情况是因为在awaiting 代码在其被调用的同一上下文中恢复之后(在您的情况下 - GUI 线程)。并且由于当前等待任务完成的 GUI 线程(通过ResultWait())出现死锁,并且永远不会调用await 关键字之后的代码。 ConfigureAwait(false) 指定可以忽略当前上下文,从而允许您的代码成功完成。更多细节在这里:http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html

【讨论】:

  • 似乎工作得非常好!您会好心改进您的答案并解释这到底是做什么的吗?对于第二行更改,您需要删除AsTask()。你可以使用await file.OpenStreamForReadAsync().ConfigureAwait(false);