Xamarin.Forms.iOS调用ObservableCollection.Remove()索引越界异常咨询
异常成因
- iOS平台的UIKit框架有强制线程规则:所有和UI渲染绑定的数据源操作,必须在主线程(UI线程)执行。你绑定到CollectionView的
ObservableCollection属于UI关联数据源,当你在非主线程直接调用_observableCollectionObj.Remove(data)时,会出现两个线程同时操作集合索引的时序冲突:UI线程的CollectionView正在按旧的集合长度读取索引做布局计算,后台线程已经提前删除了集合元素,就会直接抛出System.ArgumentOutOfRangeException,提示索引超出集合范围。 - Android、UWP平台没有触发异常的核心原因是这两个平台的原生列表控件做了容错兼容:Android的RecyclerView、UWP的原生列表控件会自动把非UI线程发起的集合变更请求封送到UI线程排队执行,不会出现跨线程同时读写集合的时序冲突,所以相同代码可以正常运行。但这种非UI线程修改UI绑定数据源的写法本身不符合跨平台UI开发规范,只是两个平台做了隐式兜底。
修复逻辑说明
你测试有效的Device.BeginInvokeOnMainThread包裹写法,本质是把集合删除操作强制调度到UI线程队列执行,此时集合的修改操作和CollectionView的索引读取、布局刷新逻辑都在同一个线程按顺序执行,不会出现读写时序冲突,异常自然消失。
开发建议:所有绑定到UI控件的ObservableCollection的增、删、改、清空操作,全平台都建议统一放到主线程执行,不要依赖平台的隐式容错,避免后续平台版本更新、自定义控件逻辑接入时触发同类跨线程异常。
内容的提问来源于stack exchange,提问作者Manish Kumar
相关产品推荐
相关产品推荐

