reactiveCommand and threadproblem

455 views
Skip to first unread message

jmwatte

unread,
May 2, 2012, 5:52:19 PM5/2/12
to reacti...@googlegroups.com
I have the following viemodel that I bind to a datacontext.
The command is bound to a button.
 It displays what it should except when the inputtext is empty , I get the "The calling thread cannot access this object because a different thread owns it."-message.
Any idea how I should go about pinpointing this problem and/or how to solve it?
Ooh... and any suggestions to "make it better"... I appreciate them very much.
thx for reading
jm




 public class MainWindowVM : ReactiveValidatedObject
    {

        string _inputtext;
        public string inputtext
        {
            get { return _inputtext; }
            set { this.RaiseAndSetIfChanged(x => x.inputtext, value); }
        }
        public ReactiveCommand replacetextcommand { get; protected set; }
        ObservableAsPropertyHelper<string> _displaytext;
        public string displaytext { get { return _displaytext.Value; } }

        public MainWindowVM()
        {
            var ob = this
                             .ObservableForProperty(x => x.inputtext)
                             .Select(x => x.Value.ToUpper())
                             .Delay(TimeSpan.FromSeconds(1))
                             .ToProperty(
                             this, x => x.displaytext);

            var isinputtextempty = this
                            .ObservableForProperty(x => x.inputtext)
                            .Select(s => s.Value)
                            .Select(s => !string.IsNullOrEmpty(s));

            replacetextcommand = new ReactiveCommand(isinputtextempty, null);
            replacetextcommand.Subscribe(_ => inputtext = "this is the standardtext");
            replacetextcommand.Execute(null);

        }
    }

Paul Betts

unread,
May 2, 2012, 6:32:54 PM5/2/12
to reacti...@googlegroups.com
I'm not quite sure what you're trying to do, but you probably want to
specify RxApp.DeferredScheduler in your Delay operator.

--
Paul Betts <pa...@paulbetts.org>

jmwatte

unread,
May 3, 2012, 2:49:53 AM5/3/12
to reacti...@googlegroups.com

Hello Paul,
I'm just trying out some things to learn RUI. I came across this http://reactiveproperty.codeplex.com/ and I was trying to translate it into RUI.
The buttoncommand should be enabled on the condition : !string.IsNullOrEmpty(s) (in this case when the inputtext has text...if I delete the ! ... when the inputtext is empty)
And when clicked: fill the inputtext with a string.
Problem is - either way - when the inputtext is empty I get the tread-error.
I tried it with the RxApp.DefferedScheduler in the Delay operator... but ... same error.
Thx already for answering and any other suggestions are greatly appreciated.
jm
 

Wayne

unread,
May 4, 2012, 4:45:53 AM5/4/12
to reacti...@googlegroups.com
I'm also rather new to RxUI. I really like it (thanks Paul!), but it's quite a learning curve. I downloaded RxUI 3.1, and it was linked to Reactive Extensions 1.1, not the latest 2.0, and the debug output says something about either adding a reference to System.Reactive.Windows.Threading.dll [2.0] or explicitly setting RxApp.DeferredScheduler if not. I chose the easy route, of setting RxApp.DeferredScheduler = DispatcherScheduler.Instance in my WPF App constructor. I'm not sure if this is the correct thing to do, but it solved the same error that you're experiencing.
-Wayne

jmwatte

unread,
May 4, 2012, 10:01:43 AM5/4/12
to reacti...@googlegroups.com
Thanks Wayne
That solved it ....
I did...

 protected override void OnStartup(StartupEventArgs e)
 { base.OnStartup(e);
    RxApp.DeferredScheduler = System.Reactive.Concurrency.DispatcherScheduler.Instance;}

in the App.xaml.cs and... olé!!!!
 
...on with the experiments...
oh and by the way I got the same kind of errormessage. I'll put it here if someone has any use for it...
A first chance exception of type 'System.IO.FileLoadException' occurred in mscorlib.dll
'RUtestjes.vshost.exe' (Managed (v4.0.30319)): Loaded 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.ServiceModel\v4.0_4.0.0.0__b77a5c561934e089\System.ServiceModel.dll'
'RUtestjes.vshost.exe' (Managed (v4.0.30319)): Loaded 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Runtime.Serialization\v4.0_4.0.0.0__b77a5c561934e089\System.Runtime.Serialization.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
INFO Logger: *** NLog was not configured, setting up a default configuration ***
ERROR Logger: System.IO.FileLoadException: Could not load file or assembly 'System.Reactive.Windows.Threading, Version=2.0.20304.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
File name: 'System.Reactive.Windows.Threading, Version=2.0.20304.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'
   at System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMarkHandle stackMark, IntPtr pPrivHostBinder, Boolean loadTypeFromPartialName, ObjectHandleOnStack type)
   at System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean loadTypeFromPartialName)
   at System.RuntimeType.GetType(String typeName, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark)
   at System.Type.GetType(String typeName, Boolean throwOnError)
   at ReactiveUI.RxApp.findDispatcherScheduler() in Z:\Dropbox\ReactiveUI_External\ReactiveUI\RxApp.cs:line 342    


and a bit later on ....




ERROR Logger: *** WPF Rx.NET DLL reference not added - using Event Loop ***
ERROR Logger: Add a reference to System.Reactive.Windows.Threading.dll if you're using WPF / SL4 / WP7
ERROR Logger: or consider explicitly setting RxApp.DeferredScheduler if not


thank you all...


Op vrijdag 4 mei 2012 10:45:53 UTC+2 schreef Wayne het volgende:

Paul Betts

unread,
May 4, 2012, 2:19:05 PM5/4/12
to reacti...@googlegroups.com
This problem is fixed in RxUI 3.1.1 which I released yesterday, sorry
about that.

--
Paul Betts <pa...@paulbetts.org>

Paul Betts

unread,
May 4, 2012, 2:19:43 PM5/4/12
to reacti...@googlegroups.com
Call stack?

--
Paul Betts <pa...@paulbetts.org>

jmwatte

unread,
May 4, 2012, 3:23:43 PM5/4/12
to reacti...@googlegroups.com
Oh no problem Paul, I appreciate it very much. I updated to 3.1.1. ... deleted the OnStartup method in the app.xaml and everything works - OK - like you said. The thread-error is gone and there are no error logger messsages anymore... Don't you love it when a plan comes together ...;) THX

jmwatte

unread,
May 21, 2012, 10:46:17 AM5/21/12
to reacti...@googlegroups.com
Paul,

This is really strange to me. The program I had worked "perfectly". This morning (21 may) I updated the RxUI-references from github to 3.1.2.0. And now my program doesn't work anymore. It hangs. If I wait long enough I get this message :

ContextSwitchDeadlock was detected
Message: The CLR has been unable to transition from COM context 0x517cc8 to COM context 0x517d80 for 60 seconds. The thread that owns the destination context/apartment is most likely either doing a non pumping wait or processing a very long running operation without pumping Windows messages. This situation generally has a negative performance impact and may even lead to the application becoming non responsive or memory usage accumulating continually over time. To avoid this problem, all single threaded apartment (STA) threads should use pumping wait primitives (such as CoWaitForMultipleHandles) and routinely pump messages during long running operations.

Yesterday it was smooth as a knife through butter :-(
 
I think the important part of my program is this

 ExecuteSearch = new ReactiveAsyncCommand(null, 1, RxApp.DeferredScheduler);
            var results = ExecuteSearch.RegisterAsyncFunction(term => GetSearchResultsFromEverythingSearch((List<string>)term));
            _MusicFromSearchResult = new ObservableAsPropertyHelper<List<string>>(results, _ => raisePropertyChanged("MusicFromSearchResult"));

            RemoveDoubleSearchtermsFromList = new ReactiveAsyncCommand(null, 1, RxApp.DeferredScheduler);
            var sl = RemoveDoubleSearchtermsFromList.RegisterAsyncFunction(term => makesafeList((string)term));
            _SearchTermWithoutDoubles = new ObservableAsPropertyHelper<List<string>>(sl, _ => raisePropertyChanged("SearchTermWithoutDoubles"));

            _HowMuchMusicIsFound = new ObservableAsPropertyHelper<int>(_MusicFromSearchResult.Select(x => x.Count), x => raisePropertyChanged("HowMuchMusicIsFound"), 0);

            ReloadAllMusic = new ReactiveAsyncCommand(null, 1,  RxApp.DeferredScheduler);
            ReloadAllMusic.RegisterAsyncAction(x => _ReloadCollection());

            Tree = MakeTreeitems.FromThisList(_ES.muziek);
            ReactiveAsyncCommand treeviewOn = new ReactiveAsyncCommand(null, 1);
            ReactiveAsyncCommand listboxviewOn = new ReactiveAsyncCommand(null, 1);


            this.ObservableForProperty(x => x.SearchTerm)
                .Select(x => x.Value.Trim())
                .Where(x => !String.IsNullOrWhiteSpace(x))
                .DistinctUntilChanged()
                .ObserveOn(RxApp.DeferredScheduler)
                .Subscribe(RemoveDoubleSearchtermsFromList.Execute);

            this.ObservableForProperty(x => x.SearchTermWithoutDoubles)
                .DistinctUntilChanged()
                .Throttle(TimeSpan.FromMilliseconds(800))
                .Select(x => x.Value)
                .ObserveOn(RxApp.DeferredScheduler)
                .Subscribe(ExecuteSearch.Execute);

Any suggestions on this? I swear it worked when I went to sleep ;-)




Reply all
Reply to author
Forward
0 new messages