尝试使用PCLStorage读取文件时冻结

时间:2014-06-03 10:56:04

标签: c# ios xamarin portable-class-library

我在我的项目中使用PCLStorage库,以便我可以从我的PCL lib访问文件系统。我正在尝试按如下方式读取文件:

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

由于PCLStorage是异步的,我想在同步代码中使用它,我这样称呼它:

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

问题是当我尝试执行此代码时整个应用程序冻结。如上面的注释中所述,不执行LoadAsync方法中的代码。我正在使用最新的Xamarin 3.我的PCL库在Xamarin iOS项目中被引用。这两个项目都通过nugget引用了PCLStorage。

另一方面,正确执行以下代码:

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

1 个答案:

答案 0 :(得分:4)

这始终是灾难的潜在秘诀:

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

如果在UI线程中发生这种情况,那么基本上阻止UI线程直到任务完成 - 但任务还需要在UI线程上执行其延续。你有一个僵局。

基本上你应该尝试构建你的应用程序以更多地拥抱异步。您可以使用Task.ConfigureAwait()来安排LoadAsync中的继续执行而不是在线程池线程上执行,但是在完成之前您仍然会阻止UI,违背了异步的精神。

Asynchrony有点病毒 - 如果你试图让你的应用程序的一个部分异步,你将会遇到困难。您需要一直保持异步,至少在UI操作方面。

(如果您阻止等待PersistAsync返回的任务,顺便说一句,您将遇到类似的问题。)