Domanda

Sto usando PCLstorage Library nel mio progetto in modo che io possa accedere al filesystem dalla mia PCL Lib.Sto cercando di leggere un file come segue:

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

Poiché PcLstorage è asincrono e voglio usarlo in un codice sincronillo che lo sto chiamando come questo:

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

Il problema è che l'intera applicazione si blocca quando provo ad eseguire questo codice.Come descritto nei commenti sopra, il codice nel metodo LoadAsync non viene eseguito.Sto usando il nuovo Xamarin 3. La mia libreria PCL è referenziata nel progetto Xamarin IOS.Entrambi i progetti hanno riferimenti a pcstorage tramite pepita.

D'altra parte il seguente codice viene eseguito correttamente:

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

È stato utile?

Soluzione

Questa è sempre una ricetta potenziale per il disastro:

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

Se ciò sta accadendo nella filettatura dell'interfaccia utente, quindi blocca fondamentalmente il filo dell'interfaccia utente finché l'attività non è stata completata, ma l'attività dovrà eseguire anche le sue continuazioni sulla filettatura dell'interfaccia utente. Hai un deadlock.

Fondamentalmente dovresti provare a strutturare la tua app per abbracciare di più Asynchrony. You potrebbe utilizzare Task.ConfigureAwait() per pianificare le continuazioni in LoadAsync da eseguire invece sui fili del filo-piscina, ma si sta ancora bloccando l'UI finché non è completato, che è contro lo spirito di Asynchrony.

Asynchrony è in qualche modo virale - se si tenta di fare solo uno parte della tua app asincrona, avrai un momento difficile. Devi essere asincrono fino in fondo, almeno in termini di operazioni UI.

(Se blocchi in attesa che l'attività restituita da PersistAsync avrai un problema simile, a proposito.)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top