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

时间:2019-04-11 17:36:45

标签: c# system.reactive reactiveui

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

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

数据视图模型:

sudo cp -r /usr/lib/swift/*.dylib /Applications/Xcode.app/Contents/Frameworks
sudo touch /Applications/Xcode.app/Contents/Frameworks/.swift-5-staged

第三方库委托发送数据。

    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);
        }



我更新DataViewModel的实例。我希望,由于我安排了要在UI线程上执行的操作(上述),因此一切都会顺利进行。取而代之的是,我得到一个例外,即与DataGrid绑定的集合必须在主UI线程中进行更新。

    public void HandleData()
    {

        ImpactorResultData result;

        ... Processing ...

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

由于某些原因,两者:

        /// <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);
           });

        }

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

预先感谢您提供任何见解。

1 个答案:

答案 0 :(得分:0)

您应该能够从后台线程更新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软件包。