ReactiveUI: задача Scheudle в потоке пользовательского интерфейса из фонового потока - PullRequest
0 голосов
/ 11 апреля 2019

Мне нужно обработать большой набор данных в фоновом потоке, а затем отобразить эти данные в элементах управления DataGrid в интерфейсе WPF.Данные поступают с внешнего промышленного устройства, для которого мне предоставлена ​​сторонняя библиотека.Итак, я получаю данные в делегате из этой библиотеки.

Моя проблема в том, что мне кажется, что я не могу запланировать операцию в потоке 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.Я ожидаю, что, поскольку я запланировал выполнение операции в потоке пользовательского интерфейса (см. Выше), все будет хорошо.Вместо этого я получаю исключение, что коллекции, связанные с DataGrid, должны обновляться в основном потоке пользовательского интерфейса.

        /// <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.

Заранее благодарим вас за любые идеи.

1 Ответ

0 голосов
/ 11 апреля 2019

Вы должны иметь возможность обновить SourceList из фоновой ветки. Вам не нужна вся эта сложная логика. Вместо этого используйте System.Reactive.Linq и расширение ObserveOn() непосредственно перед привязкой к свойству, которое фактически использует ваш пользовательский интерфейс.

По вашему мнению модель:

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

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

О, и я не пользователь Wpf, но я помню, что были некоторые дополнительные пакеты ReactiveUI специально для Wpf.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...