Pergunta

Eu estou usando PCLStorage biblioteca no meu projeto para que eu possa acessar sistema de arquivos do meu PCL lib.Eu estou tentando ler um arquivo da seguinte maneira:

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

Desde PCLStorage é assíncrona e eu quero usá-lo em um syncrhonous código que eu estou chamando ele assim:

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

O problema é que todo o aplicativo trava quando tento executar este código.Como descrito em comentários acima, o código LoadAsync método não é executada.Eu estou usando a mais recente Xamarin 3.Meu PCL biblioteca é referenciado em Xamarin iOS projeto.Ambos os projectos têm referências para PCLStorage através de pepita.

Por outro lado seguinte código é executado correctamente:

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 ());
    }
Foi útil?

Solução

Este é sempre um potencial de receita para o desastre:

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

Se isso está acontecendo no thread da INTERFACE do usuário e, em seguida, você basicamente está a bloquear o thread de INTERFACE do usuário até que a tarefa foi concluída, mas a tarefa vai precisar para executar a sua continuação no thread da INTERFACE do usuário também.Você tem um bloqueio.

Basicamente, você deve estar tentando estruturar seu aplicativo para abraçar assincronia mais.Você poderia utilização Task.ConfigureAwait() para agendar a continuação em LoadAsync para executar num thread do pool de threads em vez, mas você ainda vai estar bloqueando a INTERFACE do usuário até que seja concluída, o que é contra o espírito de assincronia.

Assincronia é um pouco viral se você tentar fazer apenas um parte de seu aplicativo de forma assíncrona, você vai ter um tempo difícil.Você precisa ser assíncrona todo o caminho até, pelo menos, em termos de INTERFACE de usuário de operações.

(Se você bloquear a espera para a tarefa devolvidos por PersistAsync você vai ter um problema semelhante, a propósito.)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top