C# 使用Xamarin表单导航页面时死锁
我在使用Xamarin表单编写的移动应用程序中发现了一些奇怪的行为,前提很简单:C# 使用Xamarin表单导航页面时死锁,c#,asynchronous,mvvm,deadlock,xamarin-forms,C#,Asynchronous,Mvvm,Deadlock,Xamarin Forms,我在使用Xamarin表单编写的移动应用程序中发现了一些奇怪的行为,前提很简单: 导航到新页面(这是异步发生的) 检索一些数据(也异步地) 将数据绑定到视图 因为我使用的是mvvm,所以我不能钩住任何页面事件(出现/消失/等等),所以我只能开始从构造函数中检索数据(我知道这是个坏主意) 这就是(我认为)问题所在: 导航器(在UI线程上运行)异步解析视图和视图模型 viewmodel无法从构造函数异步加载数据,因此在加载完成之前,它会阻止UI线程 只要您的网络连接足够快,您甚至可能不会注意到它
- 导航到新页面(这是异步发生的)
- 检索一些数据(也异步地)
- 将数据绑定到视图
Task.Factory.StartNew(() => { GetData(); });
在构造函数中,这大约80%的时间都可以工作,但正如我发现的,启动一个新任务并不保证有一个新线程
因此,每隔一段时间,数据检索任务就会在UI线程上运行,阻塞它,加载时间稍长,导致崩溃
有没有一种使用mvvm异步加载数据的干净方法?好的,所以我发现了问题。这确实是一个网络代码阻塞应用程序的问题,但由于我自己编写了99%的项目,我假设所有项目都使用了我的中央网络管理器 我错了。在代码深处的某个地方,在一个基类中,有一些逻辑跟踪和加载本地化。 它的工作原理有点像这样:
- 解析页
- 解析视图模型
- 检查viewmodel转换
- 我的记忆中有必要的翻译吗
- 没有?我的本地数据库中有吗
- 还是不?尝试从本地化服务器加载它们
- 将翻译保存在数据库和内存中,并将其添加到viewmodel中
- 将viewmodel绑定到视图
这基本上意味着我花了两天的大部分时间重写了整个视图解析逻辑,使其异步工作,并对翻译进行了一些预取(如有必要)。通常您希望使用
Task.Run()
。您可能想一直考虑使用wait
和async
。您仍然可以在VM中使用特殊的数据加载方法,而不是构造函数!在视图的代码隐藏中,对appearing()执行受保护的异步重写void并调用对其中vm的加载方法执行异步调用。通常情况下,async void
是一个坏主意,除非它是一个事件处理程序,因为我的try/catch不会捕获未捕获的异常,但是在异步void启动时处于活动状态的SynchronizationContext上(通常是UI线程)。它通常会导致未经处理的错误exception@Tseng我意识到async void是个坏主意,但在这种情况下,实际上没有什么可以返回的。获取数据,将其绑定到视图,如果发生错误,则记录该数据并通知用户。那么,我该如何改变它呢?@depchie我正试图将所有逻辑排除在“代码落后”之外,否则它会很快变成意大利面条。