使用WP8.1 StorageFile Api从存储中读取xml文件

时间:2014-04-26 13:04:47

标签: xml asynchronous async-await windows-8.1 windows-phone-8.1

我的应用程序应使用StorageFile API从存储中读取xml文件。这必须是异步的,因为StorageFile API仅提供async方法。

构造函数调用方法CallAsyncMethod(),调用和(应该)等待LoadXmlFromStorageAsync方法。

DataAccess()构造函数不等待CallAsyncMethod()并在加载XML文件之前完成。因此,当我调用xmlData方法时,GetElement()变量不会被初始化。这是因为构造函数不会等待异步方法完成。

我该如何解决这个问题?

我想我只是没有得到async / await的东西。

使用DataAccess类

var dataAccess = new DataAccess();
dataAccess.GetElement("test"); //NullReferenceException

DataAccess类

public sealed class DataAccess
{
    private const string FileName = "data.xml";
    private const string FilePath = @"ms-appx:///Data/";
    private XDocument xmlData;

    public DataAccess()
    {
        //need to wrap this call, the async keyword does not work for construtor
        CallAsyncMethod();
    }

    private async void CallAsyncMethod()
    {
        await LoadXmlFromStorageAsync();
    }

    private async Task LoadXmlFromStorageAsync()
    {
        var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri(string.Concat(FilePath, FileName)));

        using (var stream = await file.OpenStreamForReadAsync())
        {
            this.xmlData = XDocument.Load(stream);
        }
    }

    public IEnumerable<XElement> GetElement(string nodeName)
    {
        //NullReferenceException because xmlData is not initializied yet
        return this.xmlData.Descendants(nodeName).ToList();
    }
}

1 个答案:

答案 0 :(得分:4)

除非您强行同步代码,否则基本上您无法执行您正在执行的操作。但是,我会建议一种替代方法,等待GetElement被调用(如果以前没有调用过)。当然,这不是一个线程安全的解决方案。

public sealed class DataAccess
{
    private const string FileName = "data.xml";
    private const string FilePath = @"ms-appx:///Data/";
    private XDocument xmlData;

    public DataAccess()
    {
    }

    private async Task<XDocument> LoadXmlFromStorageAsync()
    {
        var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri(string.Concat(FilePath, FileName)));

        using (var stream = await file.OpenStreamForReadAsync())
        {
            return XDocument.Load(stream);
        }
    }

    public async Task<IEnumerable<XElement>> GetElement(string nodeName)
    {
         if (this.xmlData == null)         
             this.xmlData = await LoadXmlFromStorageAsync();

         return this.xmlData.Descendants(nodeName).ToList();
    }

}