Windows 8 从App.OnSuspending调用StorageFolder.CreateFileAsync时崩溃

Windows 8 从App.OnSuspending调用StorageFolder.CreateFileAsync时崩溃,windows-8,visual-studio-2012,async-await,windows-store,Windows 8,Visual Studio 2012,Async Await,Windows Store,我的Win RT应用程序在Windows 8 beta版上与VS2012RC配合使用,现在在visual studio和Windows 8 pro的最终版本中遇到了一个问题,即仅当我将调试器断点设置为文件创建方法时,才能在OnSuspend中创建/打开文件 private void OnSuspending(object sender, SuspendingEventArgs e){ var deferral = e.Suspending

我的Win RT应用程序在Windows 8 beta版上与VS2012RC配合使用,现在在visual studio和Windows 8 pro的最终版本中遇到了一个问题,即仅当我将调试器断点设置为文件创建方法时,才能在OnSuspend中创建/打开文件

private void OnSuspending(object sender, SuspendingEventArgs e){                        
     var deferral = e.SuspendingOperation.GetDeferral();                       
     if (null != m_document) Save();
     deferral.Complete();
}

async void Save(){
    var folder = KnownFolders.DocumentsLibrary;       
    var file = await folder.CreateFileAsync(GetFileName(),Windows.Storage.CreationCollisionOption.ReplaceExisting);                

    var xDoc = GetXDocument();
    using (var stream = await file.OpenStreamForWriteAsync()){
       xDoc.Save(stream);                    
    }           
}
  • 如果我在
    StorageFile=wait上设置断点
    folder.CreateFileAsync(…
    ),调试器将输入 继续,一切正常

  • 但是,如果我不设置断点,文件将被创建,但是 不会保存xml的内容(文件为空)

  • 如果我在
    StorageFile file=await folder.CreateFileAsync(…
    行)下面设置断点,调试器将永远不会进入


有人有什么想法吗?我还测试了一个使用
文件夹的版本。OpenStreamForWriteAsync
,效果非常相似。

你的时间不多了。开始时大约有5秒,但如果你不声明你将使用它,那么你的时间就会缩短。试试这个:

private async void OnSuspending(object sender, SuspendingEventArgs e)
{
    var deferral = e.SuspendingOperation.GetDeferral();
    try
    {
        await Task.Delay(1000);
        Debug.WriteLine("Done");
    }
    finally
    {
        deferral.Complete();
    }
}
有关更多详细信息,请参阅。有关正式文档,请参阅:

请注意,当应用程序正在运行时,是否需要执行异步工作 暂停您需要将暂停的完成推迟到 您的工作已完成。您可以在 SuspendingOperation对象(可通过事件参数获得)延迟 在调用 返回了SuspendingDeleral对象


问题是对Save方法的调用。只等待了第一部分(文件的创建),第二部分(保存XML)是异步完成的,因此挂起操作的延迟直到保存过程结束

避免此问题的一个可能解决方案是明确等待保存操作的完成。这可以通过将OnSuspending方法声明为
aysnc
,然后使用wait关键字等待保存操作的完成来实现(请注意保存方法的任务返回类型)


我希望这篇文章能帮助其他陷入同样陷阱的人(我想知道为什么w8的beta版没有出现问题,但我认为MS已经优化了应用程序终止过程,因此在暂停过程之后,没有太多时间进行意外工作)…

是否完成操作的时间不够了?@mydogisbox:似乎是。但我不知道为什么。Save()中的wait命令似乎不是等到创建时才执行,而是立即返回(或在文件创建后执行)这也是我看到的,如果我在每次方法调用之后添加Debug.WriteLine-calls。如果没有断点,代码将永远不会到达“var xDox=GetXDocument()”-调用。它在创建文件后返回(但没有异常)。谢谢你的回答!遗憾的是,这并不能解决问题。如果你看我的代码示例,我已经推迟了暂停,我只是为了示例的简单性删除了所有异常处理。但是这没有什么区别。我发现了问题。请看我的答案,再次感谢你的帖子。@HCL我给出的解决方案是w你需要什么…我只是无意中遗漏了两个关键部分…我现在把它们放回了。别忘了在最后调用
deleral.Complete();
。@mydogisbox:谢谢,但是“delerall.Commit()”始终在,请看OnSuspend的实现。我只是删除了try/finally以使示例更小。问题不在于XML的完整性,而在于XML的序列化。在我的初始例程(Save)中,我没有注意到该方法将部分执行异步(请参阅“wait folder.Create…”后面的代码)。解决方案是等待整个方法完成(请参阅OnSuspending中的wait和Save()的返回类型“Task”)。
private async void OnSuspending(object sender, SuspendingEventArgs e){                        
     var deferral = e.SuspendingOperation.GetDeferral();                       
     if (null != m_document) await Save();
     deferral.Complete();
}

async Task Save(){
    var folder = KnownFolders.DocumentsLibrary;       
    var file = await folder.CreateFileAsync(GetFileName(),Windows.Storage.CreationCollisionOption.ReplaceExisting);                

    var xDoc = GetXDocument();
    using (var stream = await file.OpenStreamForWriteAsync()){
       xDoc.Save(stream);                    
    }           
}