【问题标题】:I get System.UnauthorizedAccessException while loading XML from disk从磁盘加载 XML 时出现 System.UnauthorizedAccessException
【发布时间】:2012-10-24 08:32:28
【问题描述】:

我正在开发 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 的东西很陌生。

【问题讨论】:

  • 那么,如果您只是导航到您能够读取文件的文件夹?
  • 您对该文件夹或文件的权限是多少,您是否以管理员模式启动了 VS?
  • Click 事件一个接一个发生得很快?可能是两个LoadXmlFromLocalFolderAsync 正在同时执行,或者与另一个线程尝试使用文件时文件被一个线程持有的事实有关。
  • @CoralDoe 我的想法是一样的。如果我快速触发事件,肯定会发生错误。有什么解决办法吗? @Larry 应该不是问题。我正在使用推荐用于沙盒本地和漫游存储的应用程序 AppData 文件夹。此外,它有时确实能够访问该文件。 @awright18 无意冒犯,但您是否错过了 StorageFile 创作的路线?

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


【解决方案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

【讨论】:

  • 我认为禁用按钮方法不起作用。 (请参阅另一个答案的评论。)关于try-catch-finally 块:我应该放什么catchfinally?如果我选择显示“抱歉,出了点问题”。消息,它们会太多。仅在启动时将 XML 加载到 XDocument 并定期写入文件是一种好习惯吗?抱歉,我真的很陌生。
  • 您使用catch 在可视模式下记录错误或尝试解决错误(如果可以)。最后,无论发生什么,您都应该关闭文件。如果您经常写入文件,最好打开一次并在需要时使用它,并在您知道不再需要时关闭它。如果你很少使用它,最好每次都打开它。
  • 我看到this person 正在使用可绑定的方法来执行操作。这种方法对我的情况有帮助吗?我会试试try-catch-finally。显然,我需要重新构建我的应用程序!
猜你喜欢
  • 1970-01-01
  • 2018-08-03
  • 2017-07-28
  • 2020-09-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-13
  • 2010-11-02
相关资源
最近更新 更多