1

前提条件: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.app启动时,在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(); 
        .......
     }

.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.

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

4

2 回答 2

1

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

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

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

此外,不要忘记将文件包装在 using 语句中,以确保在您使用完它们后将它们关闭。像这样:

using (var ReadStream1 = await file1.OpenStreamForReadAsync() as Stream)
{
...
}
于 2012-09-13T19:16:49.510 回答
1

Jared 关于同时完成这项工作是正确的,但我不太喜欢应用程序范围的任务参考。发生这种情况的原因是因为您不能等待返回 void 的方法。您已将方法标记CheckXMLCreateXML异步无效。async 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;
}
于 2012-09-13T23:46:47.093 回答