[BUG] RxApp.MainThreadScheduler wrong thread on Server-Side Blazor
I tested DynamicData with Server-Side Blazor in combination with RxUI.
The first Exceptions (System.InvalidOperationException: Collection was modified) came when ReadOnlyObservableCollection<> are accessed in the Blazor's renderer while DD updates the collections (with i.e.: observableChangeSet.observeOn(RxApp.MainThreadScheduler).Bind(out list)...).
The RxApp.MainThreadScheduler obviously doesn't run on the same thread as Blazor's renderer.
After some searching I found that the Dispatcher class exist in Microsoft.AspNetCore.Components.Dispatcher that's may used for the Blazor's renderer.
An explicit scheduler implementation for server-side Blazor might missing?
Hey @bergi9 :wave:,
Thank you for opening an issue. We will get back to you as soon as we can. Also, check out our Open Collective and consider contributing financially.
https://opencollective.com/reactiveui
PS.: We offer
prioritysupport for all financial contributors. Don't forget to addprioritylabel once you start contributing :smile:
An advanced, composable, functional reactive model-view-viewmodel framework for all .NET platforms!
The problem is blazor has a dispatcher per page and not a overall consistent thread for rendering. We might need to rethink rxapp static methods at some stage
So the solution for now would be a ISchedulerProvider service registered as scoped service if I implement an IScheduler with the dispatcher's class? If then which base class for IScheduler should I take?
@bergi9
Can you provide an example illustrating the problem? I have a SPA project using DD as well and made some stress testing for the page rendering but I couldn't reproduce the synchronization problem. Maybe I have solved the StateHasChanged Invokation differently.
Indeed using .ObserveOn(RxApp.MainThreadScheduler) doesn't make sense for Blazor yet.
I think I may have encountered this issue.
The application works fine while debugging through VS 2019, Start Debug, but running the application with dotnet run fails to resolve a certain Observable.
For anyone encountering this issue: Blazor Server and Blazor Hybrid provide a synchronization context that can be used to schedule UI updates on. So the following code is usually enough:
.ObserveOn(new SynchronizationContextScheduler(SynchronizationContext.Current))
This code captures the current Synchronization context, so it has to be executed within one of the overridden component lifecycle methods. However typically whenever you create / activate a viewmodel and define observables you are in a calltree that originated from one of the component lifecycle methods, so then it's safe.
If you are not just split the capture and usage of the synchronization context like this:
// capture the context on some render thread code:
var context = SynchronizationContext.Current;
//...
// use the context in some code that defines this observable outside the render thread:
.ObserveOn(new SynchronizationContextScheduler(context))