2012-08-16 22 views
5

VS2012RCをWindows 8ベータ版で使用していたMy Win RTアプリケーションは、Visual StudioとWindows 8の最終版に問題があり、ファイルの作成/開くOnSuspending内では、デバッガブレークポイントをファイル作成メソッドに設定した場合にのみ機能します。StorageFolder.CreateFileAsyncがApp.OnSuspendingから呼び出されるとクラッシュする

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を使ったバージョンもテストしましたが、これと全く同じ効果があります。

+0

操作が完了するまでに時間がかかりますか? – mydogisbox

+0

@mydogisbox:それはそうです。しかし、なぜ私は知らない。 Save()のawaitコマンドが作成まで待たずにすぐに(またはファイルの作成後に)save関数から戻ってくるようです。すべてのメソッド呼び出しの後にDebug.WriteLine-callsを追加すると、これも表示されます。ブレークポイントがなければ、コードは決して "var xDox = GetXDocument()"コールに到達しません。ファイルの作成後に戻ります(例外はありません)。 – HCL

答えて

7

問題はSaveメソッドへの呼び出しでした。最初の部分(ファイルの作成)のみが待機され、2番目の部分(XMLの保存)は非同期に行われたため、保存プロセスが終了するまで一時停止操作の延期は行われませんでした。

この問題を回避するには、保存操作の完了を明示的に待つことが考えられます。これは、OnSuspendingメソッドをaysncと宣言し、awaitキーワードで保存操作の完了を待つことで実現できます(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);      
    }   
} 

私はこの記事が同じ落とし穴に落ちてきた他の誰か(問題はW8のベータ版で発生していない理由を私は思ったんだけど、私はMSがアプリケーションを最適化したことを考えるのに役立ちます願っていますtermination-したがって、サスペンドプロセス後に予期せぬ作業が発生する時間が少なくなります)。

+0

最後に 'deferral.Complete();'を呼び出すことを忘れないでください。 – mydogisbox

+0

@mydogisbox:ありがとうございますが、 "deferall.Commit()"は常にOnSuspendingの実装を見ていました。私はtry/finallyを削除して、例を小さくしました。問題は完全ではなく、XMLのシリアライズでした。私の初期のルーチン(Save)では、メソッドが部分的に非同期に実行されることに気づいていません(「await folder.Create ...」の後のコードを参照)。解決策は、メソッド全体の完了まで待つことでした(OnSuspendingとSave()の戻り値のType "Task"を参照してください)。 – HCL

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

詳細はhereを参照してください。あなたのアプリが はあなたが 作業が完了するまで一時停止の完了を延期する必要があります中断されているときに、非同期の作業を行う必要がある場合

注:公式ドキュメントのためのhereを参照してください。 SuspendingOperationオブジェクト(イベントargs経由で利用可能)でGetDeferralメソッドを使用すると、 が返されたSuspendingDeferralオブジェクトでCompleteメソッドを呼び出すまで、 が中断の完了を遅延させることができます。

+0

ありがとうございました!残念ながら、それは問題を解決しません。私のコード例を見ると、私はすでに中断を延期しています。例を簡単にするために例外処理をすべて削除しただけです。しかし、それは違いはありません。 – HCL

+0

私は問題を発見しました。私の答えを見て、あなたのポストにもう一度感謝します。 – HCL

+0

@HCL私が与えた解決策は、あなたが必要としていたものでした...私は2つの重要な部分を間違って省略しました...私は今戻します。 – mydogisbox

関連する問題