this.WhenAnyValue(...).InvokeCommand not always invoked in main thread

471 views
Skip to first unread message

Atle

unread,
Feb 24, 2015, 4:21:07 AM2/24/15
to reacti...@googlegroups.com
Hi!

I have a Reactive command which reads a bunch of data and tries to create SciChart renderable series. The SciChart classes must be created in the UI thread. I invoke the command using:

this.WhenAnyValue(x => x.SelectedAnalysis)
     .Throttle(TimeSpan.FromSeconds(1), RxApp.MainThreadScheduler)
     .ObserveOn(RxApp.MainThreadScheduler)
     .InvokeCommand(this, x => x.CreateSeries);

However, the command is not always invoked on the main thread. Especially if the SelectedAnalysis property is changed multiple times within a second:

CreateSeries = ReactiveCommand.CreateAsyncTask(
                async _ =>
                {
                    IScoreAnalysisSetup setup = ActiveSetup;
                    Tuple<ScoreAnalysisIdentifier, ScoreAnalysisProperty> selectedAnalysis = SelectedAnalysis;

                    if (setup == null || selectedAnalysis == null)
                        return;

                    PlotData truthData = await CreateTruthSeriesAsync(setup, selectedAnalysis);

                    IList<PlotData> plotDatas = new List<PlotData>();
                    plotDatas.Add(truthData);

STA crash-->var chartViewModels = plotDatas.Select(CreateIncludedTruthSeries).ToList();
                    SetSeriesCollection(chartViewModels);
                });

What am I doing wrong? I have tried returning the PlotData list from the command and subscribe like this:

            CreateSeries.ObserveOn(RxApp.MainThreadScheduler)
                        .Subscribe(x =>
            {
                if (x == null)
                {
                    SetSeriesCollection();
                    return;
                }

                var chartViewModels = x.Select(CreateIncludedTruthSeries).ToList();
                SetSeriesCollection(chartViewModels);
            });

However, this does not help at all. Still things are being invoked on a background thread.

Sincerely
Atle

paul....@gmail.com

unread,
Mar 3, 2015, 11:30:30 PM3/3/15
to reacti...@googlegroups.com
Hey Atle,

What thread this ends up on depends on the implementation of CreateTruthSeriesAsync. In that async block though, you need to not touch any UI elements or things bound to UI elements. Subscribe to the command and mutate UI elements there

Paul



--
You received this message because you are subscribed to the Google Groups "ReactiveUI mailing list" group.
To unsubscribe from this group and stop receiving emails from it, send an email to reactivexaml...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Atle

unread,
Mar 4, 2015, 2:01:52 AM3/4/15
to reacti...@googlegroups.com
Hi Paul,

CreateTruthSeriesAsync is only reading data and putting it in that PlotData class. Then, below the call to that function, i expect to be back on the UI thread, however, this is not always the case. The line "var chartViewModels = plotDatas.Select(CreateIncludedTruthSeries).ToList();" must be run on the UI thread, but throws an exception when not. There seems to be something wrong with the RxApp.MainThreadScheduler. When setting it manually things are working better. 

            RxApp.MainThreadScheduler = DispatcherScheduler.Current;
            RxApp.TaskpoolScheduler = TaskPoolScheduler.Default;

It might be worth to mention that I have compiled ReactiveUI from source and strong-named the dlls due to my application being a plug-in to another. Maybe I have forgotten something here? This is a Windows WPF application by the way.

- Atle
Reply all
Reply to author
Forward
0 new messages