问题描述
我的应用程序应该使用 StorageFile API
从存储器读取XML文件。这有许多工作要做异步因为他 StorageFile API
只提供了异步
方法。
构造函数调用方法 CallAsyncMethod()
这就要求和(应该)等待 LoadXmlFromStorageAsync
方法。
的数据访问()
构造函数不等待 CallAsyncMethod()
并完成之前的XML文件加载。在 XMLDATA
变量时,我称之为 GetElement()
方法,因此未初始化。这是因为构造函数不等待异步方法来完成。
我该如何解决这个问题?
我想我只是不明白异步/的await的事情。
数据访问类的使用
VAR数据访问=新的DataAccess();
dataAccess.GetElement(测试); //的NullReferenceException
数据访问类
公共密封类数据访问
{
私人常量字符串文件名=data.xml中;
私人常量字符串的文件路径= @MS-APPX:///数据/;
私人的XDocument XMLDATA; 公开数据访问()
{
//需要包装此调用,async关键字不适用于construtor工作
CallAsyncMethod();
} 私人异步无效CallAsyncMethod()
{
等待LoadXmlFromStorageAsync();
} 私人异步任务LoadXmlFromStorageAsync()
{
var文件=等待StorageFile.GetFileFromApplicationUriAsync(新的URI(string.Concat(文件路径,文件名))); 使用(VAR流=等待file.OpenStreamForReadAsync())
{
this.xmlData = XDocument.Load(流);
}
} 公共IEnumerable的<&的XElement GT; GetElement(字符串节点名称)
{
//因为的NullReferenceException XMLDATA尚未initializied
返回this.xmlData.Descendants(节点名称).ToList();
}
}
从本质上讲,你不能这样做,你在做什么,除非你强行同步code。不过,我会建议另一种方法,你曾经等待 GetElement
被称为(如果它没有被称为previously)。当然,这不是一个线程安全的解决方案。
公共密封类数据访问
{
私人常量字符串文件名=data.xml中;
私人常量字符串的文件路径= @MS-APPX:///数据/;
私人的XDocument XMLDATA; 公开数据访问()
{
} 私人异步任务<&的XDocument GT; LoadXmlFromStorageAsync()
{
var文件=等待StorageFile.GetFileFromApplicationUriAsync(新的URI(string.Concat(文件路径,文件名))); 使用(VAR流=等待file.OpenStreamForReadAsync())
{
返回XDocument.Load(流);
}
} 公共异步任务<&IEnumerable的LT;的XElement>> GetElement(字符串节点名称)
{
如果(this.xmlData == NULL)
this.xmlData =等待LoadXmlFromStorageAsync(); 返回this.xmlData.Descendants(节点名称).ToList();
}
}
My application should read an xml file from storage using the StorageFile API
. This has to be done async since he StorageFile API
provides only async
methods.
The Constructor calls the method CallAsyncMethod()
which calls and (should) await the LoadXmlFromStorageAsync
method.
The DataAccess()
constructor does not wait for the CallAsyncMethod()
and completes BEFORE the XML file is loaded. The xmlData
variable is therefore not initialized when i call the GetElement()
method. This is because the constructor does not wait for the async method to complete.
How can I fix this?
I guess i just don't get the async/await thing.
usage of DataAccess class
var dataAccess = new DataAccess();
dataAccess.GetElement("test"); //NullReferenceException
DataAccess class
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();
}
}
Essentially you can't do what you're doing, unless you forcefully synchronize the code. However, I would recommend an alternative approach, where you await once GetElement
is called (if it haven't been called previously). Of course, this is not a thread-safe solution.
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();
}
}
这篇关于从存储器读取XML文件WP8.1 StorageFile阿比的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!