从磁盘加载XML时,我得到System.UnauthorizedAccessException

时间:2012-10-24 08:32:29

标签: c# windows-8 microsoft-metro linq-to-xml

我正在使用Windows 8 XAML / C#商店应用。我想在应用的生命周期内多次将Windows.Storage.ApplicationData.Current.LocalFolder的XML加载到XDocument。但是,当我尝试加载文件时收到System.UnauthorizedAccessException。以下是我的方法:

添加到XML:

private async void AddCategoryButton_Click(object sender, RoutedEventArgs e)
{
    XDocument CategoryListXDoc = await LoadXmlFromLocalFolderAsync("Categories.xml");
    CategoryListXDoc.Element("CategoryList").Add(
        new XElement("Category", new XAttribute("Id", Guid.NewGuid()), AddCategoryTextBox.Text));
    SaveXDocToLocalFolderAsync("Categories.xml", CategoryListXDoc);
}

仅用于调试目的:

private async void Button_Click_2(object sender, RoutedEventArgs e)
{
    XDocument TempXDoc = await LoadXmlFromLocalFolderAsync("Categories.xml");
    Debug.WriteLine(TempXDoc);
}

加载和保存方法:

private async Task<XDocument> LoadXmlFromLocalFolderAsync(string FileName)
{
    var LocalFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
    StorageFile CategoryListFile = await LocalFolder.GetFileAsync(FileName);
    var stream = await CategoryListFile.OpenStreamForReadAsync() as Stream;
    XDocument TempXDoc = XDocument.Load(stream);
    stream.Flush();
    return TempXDoc;            
}
private async void SaveXDocToLocalFolderAsync(string Filename, XDocument XDocToSave)
{
    var LocalFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
    StorageFile CategoryListFile = await LocalFolder.CreateFileAsync(Filename, CreationCollisionOption.ReplaceExisting);
    var stream = await CategoryListFile.OpenStreamForWriteAsync() as Stream;
    XDocToSave.Save(stream);
    stream.Flush();
}

如果我重复触发Click个事件,则抛出异常。没有特定的场景。有时会发生错误,有时则不会。我哪里错了?我对asyncawait这些东西很新。

1 个答案:

答案 0 :(得分:1)

您可以检查真正有两个线程是否正在尝试访问该文件。查看异常的MessageStackTrace会有所帮助。 像

这样的事情
  Message=Invalid cross-thread access.
 StackTrace:
   at MS.Internal.XcpImports.CheckThread()

应该出现在那里。

此问题的解决方案是使用LoadXmlFromLocalFolderAsync方法的锁,这样两个线程无法同时打开文件。 http://msdn.microsoft.com/en-us/library/a8544e2s(v=vs.100).aspx 另外一个很好的建议是始终管理try-catch-finally块中的文件。

但这有点脏。交互式应用程序中的问题不是允许用户像疯了一样快速点击按钮。您应该禁用按钮功能,直到当前完成。想象一下,按钮点击会发生更复杂的操作;这使得不必使用系统资源。不行。 您应该尝试使用阻止双击的方法,如下所示: http://tgynther.blogspot.ro/2011/07/aspnet-prevent-button-double-click.html