点击刷新后,查询已经返回,表格却还是旧内容;再点一次,数据又突然恢复到上一次的结果。这类问题要沿着查询、绑定和显示三个环节检查。DevExpress如何配置异步数据加载DevExpress异步刷新后界面数据未更新如何排查,下面以WinForms的GridControl为例。普通集合绑定与Instant Feedback模式采用不同的更新机制,使用前应先确认当前工程属于哪一种。
一、DevExpress如何配置异步数据加载
异步加载要解决的是等待数据时界面仍能响应。仅给方法加上async,或者显示一个等待动画,都不能证明查询已经异步执行。
1、普通集合采用异步查询后绑定
①在窗体加载或刷新事件中调用数据访问层的异步方法,通过await等待结果。支持原生异步的数据库或网络接口,可直接使用,不必再额外包一层Task.Run。
②查询完成后,在界面线程更新【DataSource】或已绑定集合。回调来自后台线程时,通过【BeginInvoke】等方式切回界面线程,不要直接操作GridControl。
③为加载过程处理异常,并恢复按钮和等待状态。异步方法内部不要再用Result或Wait阻塞界面线程,否则仍可能出现卡顿。
一次查询返回一批普通业务数据时,这条路径比较直接。先取得结果,再统一绑定,也便于检查到底是哪批数据进入了表格。
2、大数据量使用合适的异步数据源
①需要服务端排序、筛选和按需加载时,在数据源向导中选择【Asynchronous Server-Side Data Processing】,按数据访问技术配置对应的Instant Feedback数据源。
②以【EntityInstantFeedbackSource】为例,设置【KeyExpression】,在【GetQueryable】中提供查询源,在【DismissQueryable】中释放相应上下文。
③将组件绑定到GridControl的【DataSource】。这类服务端模式应直接绑定对应组件,不要再套普通BindingSource,破坏按需加载方式。
键字段应能稳定识别记录。查询源的上下文也不能在交给组件后立即释放,更不能随意与其他并发操作共用。
二、DevExpress异步刷新后界面数据未更新如何排查
先选一条确定发生变化的记录,用业务主键追踪。只看表格行数不够:更新字段时行数不变,筛选条件也可能把新增记录挡在当前视图之外。
1、检查返回结果是否已经是新值
①在查询完成处记录请求条件、记录主键和目标字段,确认结果中确实包含新值。保存数据库的操作应先完成提交,再触发读取。
②如果此处已经是旧值,继续检查查询条件、缓存、连接环境及ORM上下文。换一个干净的查询上下文作对照,比反复刷新表格更容易确认问题。
③保留异常信息。查询失败后若仍显示原数据,应向用户说明加载失败,避免把旧内容误认为最新结果。
数据库已更新,不代表当前查询一定能读到同一批数据。测试环境连错库、条件带错日期,也会呈现“刷新没效果”。
2、检查更新对象与通知机制
①核对GridControl的【DataSource】,确认修改的是当前绑定对象。局部变量接收了新列表,但控件仍绑定旧列表时,界面不会跟着变化。
②使用【BindingList
③检查列的【FieldName】是否指向预期属性。后台更新了一个字段,列却显示另一个属性或计算结果,也会让人误以为通知没有生效。
尤其要留意“新建了一个同主键对象”的情况。主键相同不等于同一个内存对象,修改新对象并不会自动改变旧列表里的那一项。
3、按绑定模式选择刷新入口
①普通列表不提供变更通知时,可在数据更新后调用【RefreshDataSource()】;若只涉及少数行,应考虑对应视图的【RefreshRow】等局部更新方法。
②Instant Feedback模式检查数据源自身的【Refresh()】,不要把普通集合的刷新写法直接搬过来。【RefreshDataSource()】不适用于直接绑定IQueryable的情况。
③复核当前筛选、排序和查找条件,按主键定位记录。调用控件【Refresh()】重绘界面,也不能代替重新查询数据库。
排查时一次只验证一个入口。把所有刷新方法连续调用一遍,即使暂时显示正确,也很难确定原来的缺口在哪里。
三、DevExpress如何避免异步结果覆盖和刷新遗漏
绑定链路确认正常后,还应测试连续操作。单次刷新没有问题,快速切换查询条件时仍可能出现旧请求覆盖新请求。
1、控制并发请求的结果落地
①普通异步查询开始时,保存本次条件快照并分配递增请求编号;返回后,只有仍属于当前查询的结果才更新【DataSource】。
②数据访问层支持取消时,可取消上一请求,但仍应保留编号核对。取消请求未必能让已经完成的回调停止执行。
③在界面线程提交结果前,检查窗体是否已经关闭。恢复加载状态时,也要确认它属于哪次请求,避免旧请求把新请求的等待提示提前清除。
例如先查A客户、随即查B客户,A请求较慢却最后返回。如果不判断结果归属,页面就可能从B客户重新跳回A客户。
2、用几种变化验证刷新链路
①分别测试新增记录、删除记录和修改已有字段,再带着筛选条件重复测试,确认集合通知与属性通知都有效。
②在数据接收、绑定完成和界面定位三个位置记录同一条业务主键,复核显示值。若使用批量更新锁,检查异常路径是否也执行了配对的结束调用。
验收时不只看“按钮能点、查询成功”,还应确认快速操作、失败重试和关闭窗体后没有遗留更新。
总结
DevExpress如何配置异步数据加载DevExpress异步刷新后界面数据未更新如何排查,可以从一条记录的新值开始,依次核对查询结果、绑定对象和通知方式。普通列表与Instant Feedback模式应使用各自适用的更新入口,重绘也不能替代数据读取。连续刷新时,还要防止旧请求覆盖当前结果。希望这些方法能帮助大家找到数据停止更新的具体环节,减少靠重复刷新碰运气的情况。欢迎有相关需求的朋友进一步交流。
