splat: [BUG] Splat.Microsoft.Extensions.DependencyInjection causes System.InvalidOperationException: Call from invalid thread
Just trying to put together Avalonia’s routing sample and Splat.Microsoft.Extensions.DependencyInjection. Pressing Go next button throws the exception below when Splat.Microsoft.Extensions.DependencyInjection is used. Works fine if services.UseMicrosoftDependencyResolver();
is commented out.
Repro: AvaRxUI.zip
System.InvalidOperationException: Call from invalid thread
at Avalonia.Threading.Dispatcher.<VerifyAccess>g__ThrowVerifyAccess|16_0() in /_/src/Avalonia.Base/Threading/Dispatcher.cs:line 77
at Avalonia.Threading.Dispatcher.VerifyAccess() in /_/src/Avalonia.Base/Threading/Dispatcher.cs:line 78
at Avalonia.AvaloniaObject.VerifyAccess() in /_/src/Avalonia.Base/AvaloniaObject.cs:line 111
at Avalonia.AvaloniaObject.GetValue[T](StyledProperty`1 property) in /_/src/Avalonia.Base/AvaloniaObject.cs:line 226
at Avalonia.Controls.Button.get_Command() in /_/src/Avalonia.Controls/Button.cs:line 138
at Avalonia.Controls.Button.CanExecuteChanged(Object sender, EventArgs e) in /_/src/Avalonia.Controls/Button.cs:line 560
at ReactiveUI.ReactiveCommandBase`2.OnCanExecuteChanged(Boolean newValue) in /_/src/ReactiveUI/ReactiveCommand/ReactiveCommandBase.cs:line 219
at System.Reactive.AnonymousSafeObserver`1.OnNext(T value) in /_/Rx.NET/Source/src/System.Reactive/AnonymousSafeObserver.cs:line 43
at System.Reactive.Sink`1.ForwardOnNext(TTarget value) in /_/Rx.NET/Source/src/System.Reactive/Internal/Sink.cs:line 49
at System.Reactive.IdentitySink`1.OnNext(T value) in /_/Rx.NET/Source/src/System.Reactive/Internal/IdentitySink.cs:line 15
at System.Reactive.Subjects.FastImmediateObserver`1.EnsureActive(Int32 count) in /_/Rx.NET/Source/src/System.Reactive/Subjects/ReplaySubject.cs:line 863
at System.Reactive.Subjects.FastImmediateObserver`1.EnsureActive() in /_/Rx.NET/Source/src/System.Reactive/Subjects/ReplaySubject.cs:line 765
at System.Reactive.Subjects.ReplaySubject`1.ReplayBase.OnNext(T value) in /_/Rx.NET/Source/src/System.Reactive/Subjects/ReplaySubject.cs:line 270
at System.Reactive.Subjects.ReplaySubject`1.OnNext(T value) in /_/Rx.NET/Source/src/System.Reactive/Subjects/ReplaySubject.cs:line 161
at System.Reactive.Sink`1.ForwardOnNext(TTarget value) in /_/Rx.NET/Source/src/System.Reactive/Internal/Sink.cs:line 49
at System.Reactive.IdentitySink`1.OnNext(T value) in /_/Rx.NET/Source/src/System.Reactive/Internal/IdentitySink.cs:line 15
at System.Reactive.Sink`1.ForwardOnNext(TTarget value) in /_/Rx.NET/Source/src/System.Reactive/Internal/Sink.cs:line 49
at System.Reactive.Linq.ObservableImpl.DistinctUntilChanged`2._.OnNext(TSource value) in /_/Rx.NET/Source/src/System.Reactive/Linq/Observable/DistinctUntilChanged.cs:line 72
at System.Reactive.Sink`1.ForwardOnNext(TTarget value) in /_/Rx.NET/Source/src/System.Reactive/Internal/Sink.cs:line 49
at System.Reactive.Linq.ObservableImpl.CombineLatest`3._.SecondObserver.OnNext(TSecond value) in /_/Rx.NET/Source/src/System.Reactive/Linq/Observable/CombineLatest.cs:line 177
at System.Reactive.Sink`1.ForwardOnNext(TTarget value) in /_/Rx.NET/Source/src/System.Reactive/Internal/Sink.cs:line 49
at System.Reactive.IdentitySink`1.OnNext(T value) in /_/Rx.NET/Source/src/System.Reactive/Internal/IdentitySink.cs:line 15
at System.Reactive.Subjects.FastImmediateObserver`1.EnsureActive(Int32 count) in /_/Rx.NET/Source/src/System.Reactive/Subjects/ReplaySubject.cs:line 863
at System.Reactive.Subjects.FastImmediateObserver`1.EnsureActive() in /_/Rx.NET/Source/src/System.Reactive/Subjects/ReplaySubject.cs:line 765
at System.Reactive.Subjects.ReplaySubject`1.ReplayBase.OnNext(T value) in /_/Rx.NET/Source/src/System.Reactive/Subjects/ReplaySubject.cs:line 270
at System.Reactive.Subjects.ReplaySubject`1.OnNext(T value) in /_/Rx.NET/Source/src/System.Reactive/Subjects/ReplaySubject.cs:line 161
at System.Reactive.Sink`1.ForwardOnNext(TTarget value) in /_/Rx.NET/Source/src/System.Reactive/Internal/Sink.cs:line 49
at System.Reactive.IdentitySink`1.OnNext(T value) in /_/Rx.NET/Source/src/System.Reactive/Internal/IdentitySink.cs:line 15
at System.Reactive.Sink`1.ForwardOnNext(TTarget value) in /_/Rx.NET/Source/src/System.Reactive/Internal/Sink.cs:line 49
at System.Reactive.Linq.ObservableImpl.DistinctUntilChanged`2._.OnNext(TSource value) in /_/Rx.NET/Source/src/System.Reactive/Linq/Observable/DistinctUntilChanged.cs:line 72
at System.Reactive.Sink`1.ForwardOnNext(TTarget value) in /_/Rx.NET/Source/src/System.Reactive/Internal/Sink.cs:line 49
at System.Reactive.IdentitySink`1.OnNext(T value) in /_/Rx.NET/Source/src/System.Reactive/Internal/IdentitySink.cs:line 15
at System.Reactive.Sink`1.ForwardOnNext(TTarget value) in /_/Rx.NET/Source/src/System.Reactive/Internal/Sink.cs:line 49
at System.Reactive.Linq.ObservableImpl.Select`2.Selector._.OnNext(TSource value) in /_/Rx.NET/Source/src/System.Reactive/Linq/Observable/Select.cs:line 47
at System.Reactive.Sink`1.ForwardOnNext(TTarget value) in /_/Rx.NET/Source/src/System.Reactive/Internal/Sink.cs:line 49
at System.Reactive.Linq.ObservableImpl.Scan`2._.OnNext(TSource value) in /_/Rx.NET/Source/src/System.Reactive/Linq/Observable/Scan.cs:line 48
at System.Reactive.SafeObserver`1.WrappingSafeObserver.OnNext(TSource value) in /_/Rx.NET/Source/src/System.Reactive/Internal/SafeObserver.cs:line 30
at System.Reactive.Sink`1.ForwardOnNext(TTarget value) in /_/Rx.NET/Source/src/System.Reactive/Internal/Sink.cs:line 49
at System.Reactive.ObserveOnObserverLongRunning`1.Drain() in /_/Rx.NET/Source/src/System.Reactive/Internal/ScheduledObserver.cs:line 732
at System.Reactive.ObserveOnObserverLongRunning`1.<>c.<.cctor>b__17_0(ObserveOnObserverLongRunning`1 self, ICancelable cancelable) in /_/Rx.NET/Source/src/System.Reactive/Internal/ScheduledObserver.cs:line 680
at System.Reactive.Concurrency.DefaultScheduler.LongRunning.LongScheduledWorkItem`1.<>c.<.ctor>b__3_0(Object thisObject) in /_/Rx.NET/Source/src/System.Reactive/Concurrency/DefaultScheduler.cs:line 181
at System.Reactive.Concurrency.ConcurrencyAbstractionLayerImpl.<>c.<StartThread>b__8_0(Object itemObject) in /_/Rx.NET/Source/src/System.Reactive/Concurrency/ConcurrencyAbstractionLayerImpl.cs:line 75
About this issue
- Original URL
- State: closed
- Created a year ago
- Comments: 16 (11 by maintainers)
The end Splat packages will be a single alternative package for Avalonia and not an additional one, and be an extension of the existing code with a single dll.
RxApp.MainThreadScheduler should be set to AvaloniaScheduler.Instance and is done in the UseReactiveUI section of Avalonia.ReactiveUI, however when initialisation of Splat with the new DI occurs the RxApp.MainThreadScheduler is reset causing the issue you experienced. We will need to document the order in which the AppBuilder extensions are added in order to ensure that things are initialised in the correct order. I will most likely wrap the UseReactiveUI inside the extension to be certain it’s done in the right order. Something like UseReactiveUiWithDryIoc(container => {})