我正在尝试将List(其中Show是我的实现IXmlSerializable的类)存储到本地隔离存储。我正在使用此页面中的代码: http://metrostoragehelper.codeplex.com/ 我已经实现了“问题”部分中建议的更改。 我从项目列表中单击时使用以下代码添加Show对象。
private async void addShowButton_Click_1(object sender, RoutedEventArgs e)
{
var isoStorage = new StorageHelper<List<Show>>(StorageType.Local);
List<Show> currentShows = await isoStorage.LoadASync("myShowsEx");
if(currentShows == null) {
currentShows = new List<Show>();
}
currentShows.Add(currentShow);
isoStorage.SaveASync(currentShows, "myShowsEx");
//Read it back, for debugging to check if it has been added properly.
List<Show> currentShowsRB = await isoStorage.LoadASync("myShowsEx"); //Exception here
}
第一个节目添加得很好,它出现在currentShowsRB列表中。单击第二个项目并调用上述方法时,最后一次LoadAsync调用发生异常:拒绝访问。 (HRESULT异常:0x80070005(E_ACCESSDENIED)) 如何解决此问题以访问本地数据存储以进行多次调用?
以下是StorageHelper的相关代码:
public async void SaveASync(T Obj, string FileName)
{
FileName = FileName + ".xml";
try
{
if (Obj != null)
{
StorageFile file = null;
StorageFolder folder = GetFolder(storageType);
file = await folder.CreateFileAsync(FileName, CreationCollisionOption.ReplaceExisting);
using (var writeStream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
Stream outStream = Task.Run(() => writeStream.AsStreamForWrite()).Result;
serializer.Serialize(outStream, Obj);
//writeStream.Dispose(); //Added and we get UnauthorizedAccessException
// outStream.Dispose(); //Added ObjectDisposedException caught in catch statement below
}
}
}
catch (Exception)
{
throw;
}
}
public async Task<T> LoadASync(string FileName)
{
FileName = FileName + ".xml";
try
{
StorageFile file = null;
StorageFolder folder = GetFolder(storageType);
file = await folder.GetFileAsync(FileName);
using (var readStream = await file.OpenAsync(FileAccessMode.Read))
{
Stream inStream = Task.Run(() => readStream.AsStreamForRead()).Result;
inStream.Position = 0;
return (T)serializer.Deserialize(inStream);
}
}
catch (FileNotFoundException)
{
//file not existing is perfectly valid so simply return the default
return default(T);
//throw;
}
catch (Exception)
{
//Unable to load contents of file
throw;
}
}
我添加了writeStream.Dispose()行,但即使包含此行,我也会得到相同的Access拒绝错误消息。如果我还包含outStream.Dispose()行,那么我会在下面的catch语句中捕获一个ObjectDisposedException。还有什么我应该做的吗?
答案 0 :(得分:2)
您不是在等待SaveAsync完成,尝试在保存仍在进行时加载。将其更改为:
//isoStorage.SaveASync(currentShows, "myShowsEx");
await isoStorage.SaveASync(currentShows, "myShowsEx");
List<Show> currentShowsRB = await isoStorage.LoadASync("myShowsEx");
编辑await
void
是一个标准问题
快速解决方法是:
await TaskEx.Run(() => isoStorage.SaveASync(currentShows, "myShowsEx"));
但您也可以在TaskEx.Run()
内移动SaveASync()
。如果名称以Async结尾,则不应为void
,而是:
Task SaveASyncT Obj, string FileName)
{
return TaskEx.Run() => { .... }
}
我不相信Serialize的异步版本,所以它保持在TaskEx.Run()
。
答案 1 :(得分:0)
此块可缩短为:
using (var readStream = await file.OpenAsync(FileAccessMode.Read))
{
return (T)serializer.Deserialize(readStream);
}
因为您可以直接从XmlSerializer类中的流读取/写入。
您可能还会发现CreationCollisionOption.ReplaceExisting可能会导致问题,OpenIfExists会导致文件被序列化程序覆盖。