当前位置: 首页 > 编程语言 > C#

在数据库游标中缓存数据,同时保持UI响应共享

时间:2023-04-11 12:07:27 C#

在数据库游标中缓存数据,同时保持UI响应我有一个填充的数据库目录和一个可用于检索对象的游标。这个目录显然可以非常大,我想做的是使用ReactiveUI来缓冲数据,同时保持UI数据绑定和响应。我按照此处的步骤将我的IEnumerable转换为IObservable,如下所示:cursor.MoveToFirst();while(status==DbStatus.OK){vardbObject=Db.Create(cursor);obs.OnNext(dbObject);status=cursor.MoveToNext();}obs.OnCompleted();返回Disposable。空的;});在我的视图类(特别是Loaded事件)中,我订阅了数据源并使用缓冲方法,希望保持UI响应。公共ObservableCollectionDbObjects{得到;放;}privateasyncvoidOnLoad(objectsender,RoutedEventArgse){varobservableData=CatalogService.Instance.DataSource.Publish();varchunked=observableData.Buffer(TimeSpan.FromMilliseconds(100));dispatcherObs=chunked.ObserveOnDispatcher(DispatcherPriority.Background);dispatcherObs.Subscribe(dbObjects=>{foreach(vardbObjectindbObjects){DbObjects.Add(dbObject);}});awaitTask.Run(()=>observableData.Connect());等待dispatcherObs.ToTask();}不幸的是,结果恰恰相反。当我的视图控件(包含绑定到DbObjects属性的简单ListBox)加载时,它不会显示任何数据,直到枚举整个目录。只有这样才能刷新UI。我是ReactiveUI的新手,但我确信这取决于手头的任务。如果我使用不当,有人有任何建议或指示吗?在继续之前,我的猜测是您可能有几个零长度缓冲区,具体取决于数据库查询花费的时间,然后是一个包含所有结果的非零长度缓冲区。您最好不要在长度和时间方面限制缓冲区大小。编辑-我只是想分析原始实现中涉及的各种线程。我不同意Paul的分析,我不认为UI线程会因数据库查询而被阻塞。我认为由于缓冲了大量结果,它被阻止了。查理-拜托,你能用代码(而不是调试器)评估数据库查询并转储你得到的缓冲区长度吗?我将注释代码以显示所涉及的所有三个线程的顺序:首先,在提供的代码之外,我假设OnLoad是通过Loaded事件调用的。(1)–UI线程调用OnLoadpublicObservableCollectionDbObjects{get;放;}privateasyncvoidOnLoad(objectsender,RoutedEventArgse){//(2)UI线程进入OnLoadvarobservableData=CatalogService.Instance.DataSource.Publish();varchunked=observableData//(6)ThreadAOnNext传入Buffer.Buffer(TimeSpan.FromMilliseconds(100));//(7)ThreadB,Buffer用来运行定时器的线程池线程vardispatcherObs=chunked//(8)ThreadBstill.ObserveOnDispatcher(DispatcherPriority.Background);//(9)非阻塞OnNexts返回到UI线程dispatcherObs.Subscribe(dbObjects=>{//(10)UI线程接收缓冲的dbObjectsforeach(vardbObjectindbObjects){//(11)UI线程在所有这些图像时受到伤害是//一次性塞进集合中-这是我打赌的问题。DbObjects.Add(dbObject);}});awaitTask.Run(()=>{//(3)ThreadA-一个线程池线程,//触发对DataSource的订阅//UIThreadis*NOTBLOCKED*由于awaitobservableData.Connect()});//(13)UI线程-Dispatcher在Create调用结束时回调这里//但是UI线程没有被阻塞!!!//(14)UIThread-Thistaskwillalreadycompleted//它导致对已经完成的已发布可观察对象的第二次订阅awaitdispatcherObs.ToTask();}publicclassCatalogService{...publicIObservableDataSource{get{returnObservable.Create(obs=>{//(4)线程A同步运行数据库查询varcursor=Database.Instance.GetAllObjects();varstatus=cursor.MoveToFirst();while(status==DbStatus.OK){vardbObject=Db.Create(cursor);//(5)线程A调用OnNextobs.OnNext(dbObject);status=cursor.MoveToNext();}obs.OnCompleted();//(12)由于Connect()returnDisposable.Empty;}),线程A最终完成订阅我认为问题是一个大缓冲区,一次将大量结果卸载到ObservableCollection会为列表框创建大量工作你的问题在这里:while(status==DbStatus.OK){vardbObject=Db.Create(cursor);obs.OnNext(dbObject);status=cursor.MoveToNext();一旦有人订阅,循环将以阻塞方式同步运行。由于您在UI线程上创建订阅(当您调用Connect时),它将在UI线程上运行整个事务。改成:以上是C#学习教程:缓存数据库游标中的数据,同时维护UI响应分享所有内容,如果对大家有用,需要详细了解C#学习教程,希望你多加注意——returnObservable.Create(obs=>{Observable.Start(()=>{varcursor=Database.Instance.GetAllObjects();varstatus=cursor.MoveToFirst();while(status==DbStatus.OK){vardbObject=Db.Create(cursor);obs.OnNext(dbObject);status=cursor.MoveToNext();}obs.OnCompleted();},RxApp.TaskPoolScheduler);returnDisposable.Empty;});如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: