尝试使用 PCLStorage 读取文件时冻结
-
21-12-2019 - |
题
我在项目中使用 PCLStorage 库,以便可以从 PCL 库访问文件系统。我正在尝试按如下方式读取文件:
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 ());
}
解决方案
这始终是灾难的潜在根源:
var task = LoadAsync<User>(UserInfoFileName);
user = task.Result;
如果这种情况发生在 UI 线程中,那么您基本上会阻塞 UI 线程,直到任务完成 - 但该任务也需要在 UI 线程上执行其延续。你陷入了僵局。
基本上,您应该尝试构建您的应用程序以更多地拥抱异步。你 可以 使用 Task.ConfigureAwait()
安排继续进行 LoadAsync
相反,您可以在线程池线程上执行,但您仍然会阻塞 UI,直到它完成,这违背了异步的精神。
异步有点病毒式传播——如果你尝试只做 一 如果你的应用程序的一部分是异步的,你将会遇到困难。您需要一直异步,至少在 UI 操作方面如此。
(如果你阻塞等待返回的任务 PersistAsync
顺便说一句,你也会遇到类似的问题。)
不隶属于 StackOverflow