5

我的 Win RT 应用程序在 Windows 8 beta 上与 VS2012RC 一起工作,现在在 Visual Studio 和 Windows 8 Pro 的最终版本中出现了问题,只有在我将调试器断点设置为文件创建方法。

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 file = await folder.CreateFileAsync(...,调试器将进入,如果我继续,一切正常。

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

  • 如果我在该行下方设置断点StorageFile file = await folder.CreateFileAsync(...,则调试器永远不会进入!

有人有想法吗?我还测试了一个使用 的版本,folder.OpenStreamForWriteAsync效果完全相同。

4

2 回答 2

7

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

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

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);                    
    }           
}

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

于 2012-08-17T09:18:27.403 回答
3

你的时间不多了。您开始时大约需要 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 对象上的 GetDeferral 方法(可通过事件参数获得)来延迟挂起的完成,直到您对返回的 SuspendingDeferral 对象调用 Complete 方法之后。

于 2012-08-17T03:24:36.980 回答