Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/295.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/35.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用Xamarin表单导航页面时死锁_C#_Asynchronous_Mvvm_Deadlock_Xamarin Forms - Fatal编程技术网

C# 使用Xamarin表单导航页面时死锁

C# 使用Xamarin表单导航页面时死锁,c#,asynchronous,mvvm,deadlock,xamarin-forms,C#,Asynchronous,Mvvm,Deadlock,Xamarin Forms,我在使用Xamarin表单编写的移动应用程序中发现了一些奇怪的行为,前提很简单: 导航到新页面(这是异步发生的) 检索一些数据(也异步地) 将数据绑定到视图 因为我使用的是mvvm,所以我不能钩住任何页面事件(出现/消失/等等),所以我只能开始从构造函数中检索数据(我知道这是个坏主意) 这就是(我认为)问题所在: 导航器(在UI线程上运行)异步解析视图和视图模型 viewmodel无法从构造函数异步加载数据,因此在加载完成之前,它会阻止UI线程 只要您的网络连接足够快,您甚至可能不会注意到它

我在使用Xamarin表单编写的移动应用程序中发现了一些奇怪的行为,前提很简单:

  • 导航到新页面(这是异步发生的)
  • 检索一些数据(也异步地)
  • 将数据绑定到视图
因为我使用的是mvvm,所以我不能钩住任何页面事件(出现/消失/等等),所以我只能开始从构造函数中检索数据(我知道这是个坏主意)

这就是(我认为)问题所在:

导航器(在UI线程上运行)异步解析视图和视图模型 viewmodel无法从构造函数异步加载数据,因此在加载完成之前,它会阻止UI线程

只要您的网络连接足够快,您甚至可能不会注意到它,但当它花费太长时间时,系统似乎认为它处于死锁状态并终止

所以我试着用

Task.Factory.StartNew(() => { GetData(); });
在构造函数中,这大约80%的时间都可以工作,但正如我发现的,启动一个新任务并不保证有一个新线程

因此,每隔一段时间,数据检索任务就会在UI线程上运行,阻塞它,加载时间稍长,导致崩溃


有没有一种使用mvvm异步加载数据的干净方法?

好的,所以我发现了问题。这确实是一个网络代码阻塞应用程序的问题,但由于我自己编写了99%的项目,我假设所有项目都使用了我的中央网络管理器

我错了。在代码深处的某个地方,在一个基类中,有一些逻辑跟踪和加载本地化。 它的工作原理有点像这样:

  • 解析页
  • 解析视图模型
  • 检查viewmodel转换
  • 我的记忆中有必要的翻译吗
  • 没有?我的本地数据库中有吗
  • 还是不?尝试从本地化服务器加载它们
  • 将翻译保存在数据库和内存中,并将其添加到viewmodel中
  • 将viewmodel绑定到视图
因为我们使用的是MVVM,所以在其余部分加载之前及时加载并显示翻译是一个挑战(我们找不到一种方法来提醒UI翻译数据库发生了变化)

因此,原作者选择同步加载翻译,正如您可能已经猜到的,这会阻止UI线程,直到它完成或花费太长时间崩溃


这基本上意味着我花了两天的大部分时间重写了整个视图解析逻辑,使其异步工作,并对翻译进行了一些预取(如有必要)。

通常您希望使用
Task.Run()
。您可能想一直考虑使用
wait
async
。您仍然可以在VM中使用特殊的数据加载方法,而不是构造函数!在视图的代码隐藏中,对appearing()执行受保护的异步重写void并调用对其中vm的加载方法执行异步调用。通常情况下,
async void
是一个坏主意,除非它是一个事件处理程序,因为我的try/catch不会捕获未捕获的异常,但是在异步void启动时处于活动状态的SynchronizationContext上(通常是UI线程)。它通常会导致未经处理的错误exception@Tseng我意识到async void是个坏主意,但在这种情况下,实际上没有什么可以返回的。获取数据,将其绑定到视图,如果发生错误,则记录该数据并通知用户。那么,我该如何改变它呢?@depchie我正试图将所有逻辑排除在“代码落后”之外,否则它会很快变成意大利面条。