2012-08-16 8 views
5

Meine Win RT-Anwendung, die mit VS2012RC auf einer Windows 8 Beta gearbeitet hat, hat jetzt mit den endgültigen Versionen von Visual Studio und Windows 8 Pro das Problem, das Erstellen/Öffnen einer Datei in OnSuspending funktioniert nur, wenn ich einen Debugger-Haltepunkt auf die Dateierstellungsmethode gesetzt habe.StorageFolder.CreateFileAsync stürzt beim Aufruf von 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);      
    }   
} 
  • Wenn ich einen Haltepunkt auf StorageFile file = await folder.CreateFileAsync(... gesetzt, geht der Debugger das und wenn ich weiterhin , alles funktioniert gut.

  • Wenn ich jedoch keinen Haltepunkt einstelle, wird die Datei erstellt, aber der Inhalt des XML wird nicht gespeichert (die Datei bleibt leer).

  • Wenn ich einen Haltepunkt unter der Zeile StorageFile file = await folder.CreateFileAsync(... setze, tritt der Debugger nie ein!

Hat jemand eine Idee? Ich habe auch eine Version getestet, die folder.OpenStreamForWriteAsync verwendet, mit dem gleichen Effekt.

+0

Ist es eventuell nicht möglich, den Vorgang zu beenden? – mydogisbox

+0

@mydogisbox: Es scheint zu. Aber ich weiß nicht warum. Es sieht so aus, als ob der Befehl warten in Save() nicht bis zur Erstellung wartet, sondern sofort (oder nach der Dateierstellung) aus der Speicherfunktion zurückkehrt. Das sehe ich auch, wenn ich nach jedem Methodenaufruf Debug.WriteLine-Aufrufe hinzufüge.Ohne einen Haltepunkt erreicht der Code niemals den Aufruf "var xDox = GetXDocument()". Es wird nach der Dateierstellung zurückgegeben (aber ohne Ausnahme). – HCL

Antwort

7

Das Problem war der Aufruf der Save-Methode. Es wurde nur auf den ersten Teil (Erstellung der Datei) gewartet, der zweite Teil (das Speichern von XML) wurde asynchron durchgeführt, und daher war die Verzögerung der Aussetzungsoperation erst am Ende des Speichervorgangs.

Eine mögliche Lösung, um dieses Problem zu vermeiden, besteht darin, explizit auf den Abschluss der Speicheroperation zu warten. Dies kann erreicht werden, indem die OnSuspending-Methode als aysnc deklariert wird und dann auf den Abschluss der Speicheroperation mit dem Schlüsselwort await gewartet wird (beachten Sie den Task-Rückgabetyp der Save-Methode).

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

Ich hoffe, dieser Beitrag hilft jemand anderes, der in die gleiche Falle gefallen ist (ich frage mich, warum das Problem mit der Beta-Version von w8 nicht aufgetreten ist, aber ich denke, dass MS die Anwendung termination- optimiert Prozess und deshalb ist weniger Zeit für unerwartete Arbeit nach dem Suspensions-Prozess) ...

+0

Vergessen Sie nicht, 'deferral.Complete();' am Ende aufzurufen. – mydogisbox

+0

@mydogisbox: Danke, aber "deferall.Commit()" war immer drin, schau dir die Implementierung von OnSuspending an. Ich habe nur den Versuch/endlich entfernt, um das Beispiel kleiner zu machen. Das Problem war nicht die Complete, sondern die Serialisierung des XML. In meiner Anfangsroutine (Speichern) habe ich nicht bemerkt, dass die Methode teilweise asynchron ausgeführt wird (siehe den Code nach dem "Warten auf Ordner. Erstellen ..."). Die Lösung war, auf die Vollendung der ganzen Methode zu warten (siehe das Warten in OnSuspending und den Rückgabetyp "Task" von Save()). – HCL

3

Sie haben keine Zeit mehr. Sie beginnen mit ungefähr 5 Sekunden, aber wenn Sie nicht erklären, dass Sie es verwenden werden, wird Ihre Zeit kurz geschnitten. Versuchen Sie Folgendes:

private async void OnSuspending(object sender, SuspendingEventArgs e) 
{ 
    var deferral = e.SuspendingOperation.GetDeferral(); 
    try 
    { 
     await Task.Delay(1000); 
     Debug.WriteLine("Done"); 
    } 
    finally 
    { 
     deferral.Complete(); 
    } 
} 

Weitere Details finden Sie unter here. Siehe here für die offizielle Dokumentation:

Hinweis Wenn Sie asynchrone Arbeit tun müssen, wenn Sie Ihre App ausgesetzt werden, um Sie Fertigstellung auszusetzen, bis verschieben müssen, nachdem Ihre Arbeit abgeschlossen ist. Sie können die GetDeferral-Methode für das SuspendingOperation-Objekt (verfügbar über die Ereignisargumente) verwenden, um die Beendigung des Suspend bis zu verzögern, bis Sie die Complete-Methode für das zurückgegebene SuspendingDeferral -Objekt aufrufen.

+0

Vielen Dank für Ihre Antwort! Leider löst es das Problem nicht. Wenn Sie sich mein Codebeispiel ansehen, verschiebe ich die Aufhebung bereits, ich habe nur die Ausnahmebehandlung zur Vereinfachung des Beispiels entfernt. Es macht jedoch keinen Unterschied. – HCL

+0

Ich habe das Problem gefunden. Bitte sehen Sie meine Antwort und nochmals Danke für Ihren Beitrag. – HCL

+0

@HCL die Lösung, die ich gab, war, was Sie brauchten ... Ich habe nur unabsichtlich die beiden Schlüsselteile weggelassen ... Ich habe sie jetzt wieder eingefügt. – mydogisbox