我有一个 Xamarin.Forms 应用程序,在我的 App 类中包含以下代码(是的,这只是演示该问题的示例):
public App()
{
BlobCache.ApplicationName = "MyApp";
BlobCache.EnsureInitialized();
// The root page of your application
MainPage = GetMainPage();
}
public object BlockingGetExternalUser()
{
return GetExternalUser().Result;
}
private async Task<object> GetExternalUser()
{
try
{
return await BlobCache.LocalMachine.GetObject<object>("user");
}
catch (KeyNotFoundException)
{
return null;
}
}
密钥“用户”不存在,因此我希望得到 KeyNotFoundException。但是我从未见过抛出此异常。相反,它只是“挂起”并且永远不会从等待 GetObject 调用中返回。
我在 Android 5.0 手机上运行这个程序。
任何想法如何解决这一问题?我是否在做一些根本性错误的事情?
更新:附注:可以尝试检查密钥是否确实存在于缓存中,然后再从缓存中检索它,而不是立即尝试 GetObject。但是,如果我没有记错的话,除了调用 GetObject 并捕获异常(如上面的示例所示)之外,没有其他方法可以进行检查。对于只想知道某项是否存在的场景来说,这似乎并不理想。也许在 Akavache 中使用“Exists()”方法会更好?或者也许我错过了什么?
Update2:更改示例以不在构造函数中使用异步方法。只是为了证明一点,这不是问题。
Update3:从构造函数中删除调用。当我从代码中的任何位置调用 BlockingGetExternalUser 时,等待仍将挂起。
你肯定陷入了僵局。引用同步等待异步操作,以及为什么Wait()会在这里冻结程序 https://stackoverflow.com/questions/14485115/synchronously-waiting-for-an-async-operation-and-why-does-wait-freeze-the-pro:
异步方法中的等待正在尝试返回 UI 线程。
由于 UI 线程正忙于等待整个任务完成,因此出现了死锁。
请注意,您的电话是.Result
意味着一个Task.Wait()
某处。
有两种解决方案:要么完全避免async
方法,或者将您的代码包装到Task.Run
像这样:
public object BlockingGetExternalUser()
{
return Task.Run<object>(() => GetExternalUser().Result);
}
(我希望它正在编译,我没有在 VS 中验证:)
根据经验,我倾向于避免async
这些天结合 SQLite 的方法。原因是大多数 SQLite 包装库使用Task.Run
提供反模式async
对其方法进行包装,而 SQLite 没有任何异步的内在符号。但请注意,将东西包裹进去是完全可以的Task.Run
使它们异步,这只是库设计者的一种反模式,向用户建议方法是异步的,而实际上它们不是。您可以在这里阅读更多相关信息:Task.Run 作为反模式? https://stackoverflow.com/questions/28766042/task-run-as-an-anti-pattern
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)