为什么这个代码块在win8 rtm中抛出异常而在win8 rp中抛出异常?

时间:2012-09-13 15:41:34

标签: c# file-io windows-8 windows-runtime visual-studio-2012

  

前提条件:Windows 8 Pro RTM + VS2012 Ultimate RTM

1.以下代码在App.xaml.cs中。   如果用户第一次打开此应用程序,该应用程序将创建一个xml。

    private async void CheckXML()
    {
        try
        {
            StorageFile file1 = await ApplicationData.Current.LocalFolder.GetFileAsync("BetterTask.xml");
        }
        catch (FileNotFoundException)
        {
            CreateXML();
        }
    }


    private async void CreateXML()
    {
        StorageFile file2 = await ApplicationData.Current.LocalFolder.CreateFileAsync("BetterTask.xml", CreationCollisionOption.ReplaceExisting);
        using (var writeStream1 = await file2.OpenStreamForWriteAsync() as Stream)
        {
            XDocument doc1 = new XDocument(              
                                            new XDeclaration("1.0", "utf-8", "yes"),  
                                            new XElement("tasks", 
                                                new XElement("task",  
                                                    new XElement("title", "Wish you enjoy this App :)"),
                                                    new XElement("due", DateTime.Now.Date.ToString("yyyy/MM/dd")))));
            doc1.Save(writeStream1);
            await writeStream1.FlushAsync();
        }
    }

2.当应用程序启动时,在MainPage.xaml中的OnNavigatedTo事件中,它将读取xml以检索数据。

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        ReadTasks("all");
        ShowTime();
    }

    private async void ReadTasks(string action)
    {
        StorageFile file1 = await ApplicationData.Current.LocalFolder.GetFileAsync(xmlfilename);
        var ReadStream1 = await file1.OpenStreamForReadAsync() as Stream;
        XDocument doc1 = new XDocument();
        doc1 = XDocument.Load(ReadStream1);
        ReadStream1.Dispose(); 
        .......
     }

0.3。 发生了什么:当应用首次启动时,以下代码会引发错误:

    var ReadStream1 = await file1.OpenStreamForReadAsync() as Stream;
  

错误:   用户代码未处理UnauthorizedAccessException   访问被拒绝。   (HRESULT异常:0x80070005(E_ACCESSDENIED))

I check the folder, the xml file is created when the error happen.

0.4。 更多东西:当我重新打开应用程序时,没有任何反应,它就像一个魅力。我不知道为什么,该应用程序在Win8 RP和VS 2012 RC中运行良好。我什么都没改,但为什么它不能在带有VC2012 RTM的Win8 RTM中运行

2 个答案:

答案 0 :(得分:1)

由于您的第二个代码块使用变量名 xmlfilename ,我不知道您是否正在尝试打开同一个文件,但我猜你是。由于在App.xaml.cs中创建文件的操作和在MainPage.xaml.cs中读取文件的操作都是异步的,因此它们可能同时发生。解决此问题的最简单方法是使用表示XML文件创建的应用程序级Task变量。像这样:

Task creatingFile = CheckXML();
createFile.Start();

现在,在您的MainPage.xaml文件中,您可以使用 creatingFile.IsCompleted (或 IsFaulted )来检查任务是否仍在运行。如果任务完成,那么您只需打开该文件即可。如果任务尚未完成,您可以使用 creatingFile.ContinueWith(...)来安排文件在创建后打开。

另外,不要忘记在using语句中包装文件,以确保在使用它们时它们已关闭。像这样:

using (var ReadStream1 = await file1.OpenStreamForReadAsync() as Stream)
{
...
}

答案 1 :(得分:1)

Jared在同一时间完成此操作是正确的,但我不太喜欢应用程序范围的任务参考。发生这种情况的原因是因为您无法等待返回void的方法。您已将方法CheckXMLCreateXML标记为async void。异步void方法是一种“即发即弃”的方法。您的代码将异步执行它。当您导航到页面时,它会尝试阅读它。

我建议创建一个读取文件的方法,如果文件只是读取,则先创建然后再读取。

选项1:

private async void ReadTasks(string action)
{
    // This is a fire and forget method

    StorageFile file = await GetXmlFile(xmlfilename);

    var ReadStream1 = await file.OpenStreamForReadAsync() as Stream;
    XDocument doc1 = new XDocument();
    doc1 = XDocument.Load(ReadStream1);
    ReadStream1.Dispose(); 
    .......
}

private async Task<StorageFile> GetXmlFile(string xmlfilename)
{
    try
    {
        StorageFile file = await ApplicationData.Current.LocalFolder.GetFileAsync(xmlfilename);
    }
    catch (FileNotFoundException)
    {
        file = await CreateXml(xmlfilename);
    }
    return file;
}

private async Task<StorageFile> CreateXML(string xmlfilename)
{
    StorageFile file = await ApplicationData.Current.LocalFolder.CreateFileAsync(xmlfilename, CreationCollisionOption.ReplaceExisting);
    using (var writeStream1 = await file2.OpenStreamForWriteAsync() as Stream)
    {
        XDocument doc1 = new XDocument(              
                                        new XDeclaration("1.0", "utf-8", "yes"),  
                                        new XElement("tasks", 
                                            new XElement("task",  
                                                new XElement("title", "Wish you enjoy this App :)"),
                                                new XElement("due", DateTime.Now.Date.ToString("yyyy/MM/dd")))));
        doc1.Save(writeStream1);
        await writeStream1.FlushAsync();
    }
    return file;
}