ReactiveUI:来自后台线程的 UI 线程上的计划任务

ReactiveUI: Scheudle task on UI thread from background thread

我需要在后台线程上处理大型数据集,然后在 WPF 界面的 DataGrid 控件中显示该数据。数据来自外部工业设备,为此我提供了第三方库。因此,我从该库的委托中获取数据。

我的问题是我似乎无法从后台线程安排对 MainUI 线程的操作,我不确定如何解决这个问题。

数据视图模型:

    public class DataViewModel : ReactiveObject
    {
        public SourceList<SummaryData> SummaryData = new SourceList<SummaryData>();
        public ReadOnlyObservableCollection<SummaryData> SummaryDataView;


        public SourceList<EnergyTable> SampleData = new SourceList<EnergyTable>();
        public ReadOnlyObservableCollection<EnergyTable> SampleDataView;


        public DataViewModel()
        {
            SummaryData.Connect()
                .Bind(out SummaryDataView)
                .Subscribe();

            SampleData.Connect()
                .Bind(out SampleDataView)
                .Subscribe();

        }

    }

第三方库委托发送数据。

        protected void OnSqlCommandCode(Tag tag)
        {
            // Process the 

            Observable.Start(
                 () => HandleData(),
                 RxApp.TaskpoolScheduler)
                 .ObserveOn(RxApp.MainThreadScheduler);
        }



数据得到处理...

    public void HandleData()
    {

        ImpactorResultData result;

        ... Processing ...

        // NOW I TRY TO UPDATE THE COLLECTIONS FROM THE MAIN UI THREAD
         Observable.Start(
            () => UpdateUiThreadCollections(result),
            RxApp.MainThreadScheduler
         );       
    }

我更新了 DataViewModel 的实例。我希望,因为我安排了在 UI 线程(上面)上执行的操作,所以一切都会顺利进行。相反,我得到一个异常,绑定到 DataGrid 的集合必须在主 UI 线程中更新。

        /// <summary>
        /// Collections tied to data linked to a UI control need to be called from the 
        /// UI thread.
        /// 
        /// The other option is to remake the ObservableRangeCollection every time
        /// from the list. 
        /// </summary>
        protected static void UpdateUiThreadCollections(
            ImpactorResultData result
        )
        {
            dataViewModel.SummaryData.Add(result.SummaryData);

            dataViewModel.SampleData.Edit(innerList =>
            {
               innerList.Clear();
               innerList.AddRange(result.Samples);
           });

        }

出于某种原因,两者:

         Observable.Start(
            () => UpdateUiThreadCollections(result),
            RxApp.MainThreadScheduler
         );     

          RxApp.MainThreadScheduler.Schedule(() =>
          {
              UpdateUiThreadCollections(result);
          });

仍在后台线程上安排操作。关于 ReactiveUI 或 Reactive Extensions,肯定有一些我不理解的地方。

提前感谢您的任何见解。

您应该能够从后台线程更新您的 SourceList。你不应该需要那么复杂的逻辑。相反,在绑定到 UI 实际使用的 属性 之前使用 System.Reactive.LinqObserveOn() 扩展名。

在您的视图模型中:

            SummaryData.Connect()
                .ObserveOn(RxApp.MainThreadScheduler)
                .Bind(out SummaryDataView)
                .Subscribe();

            SampleData.Connect()
                .ObserveOn(RxApp.MainThreadScheduler)
                .Bind(out SampleDataView)
                .Subscribe();

哦,我不是 Wpf 用户,但我记得有一些专门针对 Wpf 的额外 ReactiveUI 包。