Frage

Ich verwende in meinem Projekt die PCLStorage-Bibliothek, damit ich über meine PCL-Bibliothek auf das Dateisystem zugreifen kann.Ich versuche eine Datei wie folgt zu lesen:

static async Task<T> LoadAsync<T> (string fileName) where T : class
    {
        var rootFolder = FileSystem.Current.LocalStorage; // debugger stops here
        var m5cacheFolder = await rootFolder.GetFolderAsync (CacheFolderName); // but instead of going to this line, jumps to end of this method
        var userInfoFile = await m5cacheFolder.GetFileAsync (fileName);
        var userInfoFileContent = await userInfoFile.ReadAllTextAsync ();
        var stringReader = new StringReader (userInfoFileContent);
        var serializer = new XmlSerializer (typeof(T));
        return (T)serializer.Deserialize (stringReader);
    }

Da PCLStorage asynchron ist und ich es in einem synchronen Code verwenden möchte, nenne ich es so:

var task = LoadAsync<User> (UserInfoFileName);
user = task.Result;

Das Problem ist, dass die gesamte Anwendung einfriert, wenn ich versuche, diesen Code auszuführen.Wie in den Kommentaren oben beschrieben, wird der Code in der LoadAsync-Methode nicht ausgeführt.Ich verwende das neueste Xamarin 3.Auf meine PCL-Bibliothek wird im Xamarin iOS-Projekt verwiesen.Beide Projekte weisen über Nugget Verweise auf PCLStorage auf.

Andererseits wird folgender Code korrekt ausgeführt:

static async void PersistAsync (object obj, string fileName)
    {
        var rootFolder = FileSystem.Current.LocalStorage;
        var m5cacheFolder = await rootFolder.CreateFolderAsync (CacheFolderName, CreationCollisionOption.OpenIfExists);
        var userInfoFile = await m5cacheFolder.CreateFileAsync (fileName, CreationCollisionOption.ReplaceExisting);
        var serializer = new XmlSerializer (obj.GetType ());
        var stringWriter = new StringWriter ();
        serializer.Serialize (stringWriter, obj);
        await userInfoFile.WriteAllTextAsync (stringWriter.ToString ());
    }
War es hilfreich?

Lösung

Dies ist immer ein potenzielles Rezept für eine Katastrophe:

var task = LoadAsync<User>(UserInfoFileName);
user = task.Result;

Wenn dies im UI-Thread geschieht, blockieren Sie grundsätzlich den UI-Thread, bis die Aufgabe abgeschlossen ist – aber die Aufgabe muss ihre Fortsetzungen auch im UI-Thread ausführen.Du hast eine Sackgasse.

Grundsätzlich sollten Sie versuchen, Ihre App so zu strukturieren, dass sie mehr Asynchronität berücksichtigt.Du könnte verwenden Task.ConfigureAwait() um die Fortsetzungen einzuplanen LoadAsync stattdessen auf Thread-Pool-Threads ausführen, aber Sie werden die Benutzeroberfläche trotzdem blockieren, bis sie abgeschlossen ist, was gegen den Geist der Asynchronität verstößt.

Asynchronität ist etwas viral – wenn man versucht, es einfach zu machen eins Da ein Teil Ihrer App asynchron ist, werden Sie es schwer haben.Sie müssen bis zum Ende asynchron sein, zumindest was die UI-Operationen angeht.

(Wenn Sie das Warten auf die von zurückgegebene Aufgabe blockieren PersistAsync Du wirst übrigens ein ähnliches Problem haben.)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top