# Threading
ReactiveProperty provides execution thread control feature.
ReactiveProperty raises PropertyChanged
event on UI thread automatically.
# Change the scheduler
You can change this behavior using IScheduler
.
When the instance is created, set IScheduler
instance to raiseEventScheduler
argument.
var rp = Observable.Interval(TimeSpan.FromSeconds(1))
.ToReactiveProperty(raiseEventScheduler: ImmediateScheduler.Instance);
ReactiveCollection
and ReadOnlyReactiveCollection
raise CollectionChanged
event on UI thread same as ReactiveProperty
.
This behavior can be changed using the scheduler constructor and factory method argument.
var collection = Observable.Interval(TimeSpan.FromSeconds(1))
.ToReactiveCollection(scheduler: ImmediateScheduler.Instance);
var readOnlyCollection = Observable.Interval(TimeSpan.FromSeconds(1))
.ToReadOnlyReactiveProperty(scheduler: ImmediateScheduler.Instance);
# Change the global scheduler
You can change the ReactiveProperty's default scheduler using ReactivePropertyScheduler.SetDefault
method.
ReactivePropertyScheduler.SetDefault(TaskPoolScheduler.Default);
var taskPoolRp = new ReactiveProperty<string>();
ReactivePropertyScheduler.SetDefault(ImmediateScheduler.Instance);
var immediateRp = new ReactiveProperty<string>();
taskPoolRp.Value = "changed"; // raise event on the TaskPoolScheduler thread.
immediateRp.Value = "changed"; // raise event on the ImmediateScheduler thread.
# Change the global scheduler factory
Using the ReactivePropertyScheduler.SetDefaultSchedulerFactory
method, you can change a factory method to create the ReactiveProperty's default scheduler instance.
using System.Reactive.Concurrency;
using System.Windows;
using System.Windows.Threading;
using Reactive.Bindings;
namespace MultiUIThreadApp
{
public partial class App : Application
{
private void Application_Startup(object sender, StartupEventArgs e)
{
// Set to create a DispatcherScheduler instance when every instance is created
// for ReactiveProperty, ReadOnlyReactiveProperty, ReactiveCollection, and ReadOnlyReactiveProperty.
ReactivePropertyScheduler.SetDefaultSchedulerFactory(() =>
new DispatcherScheduler(Dispatcher.CurrentDispatcher));
}
}
}
# Rx operator
Of course, you can use the ObserveOn
extension method.
var rp = Observable.Interval(TimeSpan.FromSeconds(1))
.ObserveOn(someScheduler)
.ToReactiveProperty();
And we provide the ObserveOnUIDispatcher
extension method.
This is a shortcut of ObserveOn(ReactiveProeprtyScheduler.Default)
.
var rp = Observable.Interval(TimeSpan.FromSeconds(1))
.ObserveOnUIDispatcher()
.ToReactiveProperty();
# Caution
As a default, ReactiveProperty was designed for a single UI thread platform. It means a few features don't work on multi UI thread platforms such as UWP.
UWP has multi UI threads in the single process when multiple Windows are created.
So, in case of creating multi-windows on UWP, then you should set ImmediateScheduler
using the ReactivePropertyScheduler.SetDefault
method to disable a feature of auto dispatch events to UI thread or change to create different scheduler instances for each UI thread using the ReactivePropertyScheduler.SetDefaultSchedulerFactory
method. Or please use ReactivePropertySlim
/ ReadOnlyReactivePropertySlim
classes instead of ReactiveProperty/ReadOnlyReactiveProperty classes.