I'm new to Rx.Net and Dynamic Data and I'm currently facing a following problem by using these Reactive UI Extensions.
What I try to achieve:
Filter
operation on TaskpoolScheduler
(or in general filtering the incoming data asynchronously)SourceList
from a background threadHowever, when the SourceList
is getting filled with the data from a different task I get the 'System.NotSupportedException' in System.Reactive.dll
error. So I have to use the Dispatcher Thread.
How to fix this?
A minimal working example:
using DynamicData;
using ReactiveUI;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reactive.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace ReactiveExtensionsTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private readonly ReadOnlyObservableCollection<DataModel> _items;
public ReadOnlyObservableCollection<DataModel> Items => _items;
public MainWindow()
{
InitializeComponent();
DataContext = this;
var bgDataService = new BackroundDataService();
bgDataService
.Connect()
.ObserveOn(RxApp.TaskpoolScheduler)
.Filter(x => x.IntA % 2 == 0)
.ObserveOn(RxApp.MainThreadScheduler)
.Bind(out _items)
.Subscribe();
}
}
class BackroundDataService : IBackgroundDataService
{
private readonly SourceList<DataModel> _data = new SourceList<DataModel>();
public IObservable<IChangeSet<DataModel>> Connect() => _data.Connect();
public BackroundDataService()
{
Task.Factory.StartNew(async () =>
{
int length = 100_000;
for (int i = 0; i < length; i++)
{
_data.Add(new DataModel { IntA = i, StringB = "B {i}" });
await Task.Delay(200);
}
});
}
}
internal interface IBackgroundDataService
{
IObservable<IChangeSet<DataModel>> Connect();
}
public class DataModel
{
public int IntA { get; set; }
public string StringB { get; set; }
}
}
The Items
property is bound to a ListBox
as following <ListBox ItemsSource="{Binding Items}"/>
Have you tried
var bgDataService = new BackroundDataService();
bgDataService
.Connect()
.ObserveOn(RxApp.TaskpoolScheduler)
.Filter(x => x.IntA % 2 == 0)
.Bind(out _items)
.SubscribeOn(RxApp.MainThreadScheduler);
Might be worth a try.