任务并行库(TPL)的挑战与解决方案

任务并行库(Task Parallel Library,简称TPL)是.NET Framework中的一个库,它提供了一种简化的线程处理方式,允许开发者以更直观的方式编写并行代码。然而,在Xamarin等移动应用开发中,使用TPL可能会遇到一些挑战。本文将探讨这些挑战,并介绍一种名为“响应式任务”的解决方案。

任务并行库的承诺

当微软宣布推出任务并行库时,C#程序员们为之欢呼。简化的线程处理?库内的错误处理?似乎一切都很完美。然而,现实情况并非如此。

在C#中,一个任务(Task)需要一个根(root)来正确地等待(await)。例如:

public Task YouCanAwaitMe() { } public async Task IWillAwait() { await YouCanAwaitMe().WithoutChangingContext(); }

然而,在Xamarin应用中,并没有有效的根。例如,构造函数、内容更改、绑定上下文更改、事件处理程序、全局消息、重写和属性设置器等都不是有效的根。这会导致不安全的结果。

以下是一个虚假根的示例:

public class FalselyRootedView : ContentView { protected override async void OnBindingContextChanged() { base.OnBindingContextChanged(); await StartUpViewModel().WithoutChangingContext(); } public virtual Task StartUpViewModel() { return Task.CompletedTask; } }

虚假的根会导致任务在不受控制的情况下执行,从而导致竞态条件、变量设置不及时等问题。

输出的证明

以下是在创建ResponsiveAppDemo时的调试输出。该示例在所有禁止的区域调用了任务,包括构造函数。它在其他方面表现良好,至少符合微软的指导。因此,它类似于任何遵循阅读的人可能会产生的代码:

位置 任务类型 首次/最后一次
Views.Subviews.DashboardView RunPostConstructionTasks FIRST
ViewModels.DashboardViewModel RunPostConstructionTasks FIRST
ViewModels.DashboardViewModel RunPostBindingTasks FIRST
Views.Subviews.DashboardView RunPostBindingTasks FIRST
Views.Subviews.DashboardView RunPostConstructionTasks LAST
ViewModels.DashboardViewModel RunPostConstructionTasks LAST
ViewModels.DashboardViewModel RunPostBindingTasks LAST
Views.Subviews.DashboardView RunPostBindingTasks LAST

一切都立即运行,并且相互叠加。在其他东西堆积并试图依赖某种想象中的状态之前,没有任何东西能够正确形成。这就是导致程序挂起和崩溃的原因。

最明显的解决方案也是最糟糕的

那么,如何实现每个任务的原子完整性,而不重叠呢?试试这个:

public async void IncorrectlyRaiseATaskWithABlockingCall() { await SomeTask.Wait().WithoutChangingContext(); }

讽刺的是,这解决了并发问题,因为它在完成任务后才继续。但这代价巨大:100%的UI线程。用户立即感觉到他们的键盘死了。Wait是一个锈迹斑斑的剃须刀,藏在工具箱底部。

响应式任务库使用线程安全的“等待”策略,以及支持任务的基类,解决了这里提到的所有问题。可以轻松地将代码示例复制到自己的基视图或视图模型中,因此这种方法并不教条。

位置 任务类型 首次/最后一次
Views.Subviews.DashboardView RunPostConstructionTasks FIRST
Views.Subviews.DashboardView RunPostConstructionTasks LAST
ViewModels.DashboardViewModel RunPostConstructionTasks FIRST
ViewModels.DashboardViewModel RunPostConstructionTasks LAST
ViewModels.DashboardViewModel RunPostBindingTasks FIRST
ViewModels.DashboardViewModel RunPostBindingTasks LAST
Views.Subviews.DashboardView RunPostBindingTasks FIRST
Views.Subviews.DashboardView RunPostBindingTasks LAST
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485