ReactiveUI Command with WCF resulting in Thread error on updating of Observable Property

I am attempting to make a WCF call using ReactiveUI commands and capturing the resulting string with ObservableAsPropertyHelper. With the code below I am receiving the following error message -

"The calling thread cannot access this object because a different thread owns it"

The WCF call returns but errors on accessing the ObservableForProperty - Message and/or when raising its PropertyChanged

Let me know if anyone needs other details/code.

ViewModel: UserService.Authenticate is proxy call to a WCF endpoint

public class LoginViewModel : ReactiveObject, IRoutableViewModel
{
  public LoginViewModel(IScreen hostScreen , MainViewModel appRootViewModel, IUserService userService)
    {
        HostScreen = hostScreen;

        UserService = userService;
        Application = appRootViewModel;
        var canLogin = this.WhenAny(x => x.LoginName, x => x.Password, (l, p) =>
            !String.IsNullOrWhiteSpace(l.Value) && !String.IsNullOrWhiteSpace(p.Value));

        LoginCommand = new ReactiveCommand(canLogin);

        var loggedIn = LoginCommand.RegisterAsync(_ => Observable.Start(() =>
            {
                var request = new Request
                {
                    UserIdentity = new User.Identity
                    {
                        Login = LoginName,
                        Password = new User.Password { Old = Password }
                    }

                };
                var authenticationResult = UserService.Authenticate(request).Authenticated;

                return authenticationResult ? "Login Succeeded...Continuing"
                    : "Login Failed...Please try again";


            }));
        loggedIn.Subscribe(s =>
        {
            if (s == "Login Succeeded...Continuing to Analytics")
            {
                HostScreen.Router.Navigate.Execute(Application);
            }

        });

            message = new ObservableAsPropertyHelper<string>(loggedIn,
            s =>
            {

                raisePropertyChanged("Message");

            });

view code behind:

public partial class LoginView : IViewFor<LoginViewModel>
{
   public LoginView()
    {
        InitializeComponent();

        this.WhenAnyValue(x => x.ViewModel).BindTo(this, x => x.DataContext);
        this.Bind(ViewModel, model => model.Password, x => x.password.Text);
        this.Bind(ViewModel, model => model.LoginName, view => view.userName.Text);
        this.OneWayBind(ViewModel, model => model.Message, x => x.message.Content);
        this.OneWayBind(ViewModel, x => x.LoginCommand, x => x.login.Command);
    }

    public static readonly DependencyProperty ViewModelProperty =
DependencyProperty.Register("ViewModel", typeof(LoginViewModel), typeof(LoginView), new PropertyMetadata(null));


    object IViewFor.ViewModel
    {
        get { return ViewModel; }
        set { ViewModel = (LoginViewModel)value; }
    }

    public LoginViewModel ViewModel
    {
        get
        {
            return (LoginViewModel)GetValue(ViewModelProperty);
        }
        set
        {
            SetValue(ViewModelProperty,
                value);
        }
    }

}

}

Answers


Most of your code is correct (except for where you set message, just use loggedIn.ToProperty), but as I recall, WCF tries to "help you out" by fiddling with SynchronizationContexts, you need to disable this (I'm not sure how to do this though)


Update: Fixed by telling the observer callbacks to run on the current synchronization context.

.ObserveOn(SynchronizationContext.Current)

So below is the LoginCommand Observable code to fix the above issues. Last line is the edit.

var loggedIn = LoginCommand.RegisterAsync(_ => Observable.Start(() =>
            {


                Session<NullT> init = new Session<NullT>
                {
                    SqlKey = System.Configuration.ConfigurationManager.AppSettings["sharedKey"].ToString()

                };

                var initResponse = UserService.Initialize(init);
                var authenticationResult = false;
                if (initResponse.SessionOk)
                {
                    initResponse.UserIdentity = new User.Identity
                    {
                        Login = LoginName,
                        Password = new User.Password { Old = Password }
                    };


                    authenticationResult = UserService.Authenticate(initResponse).Authenticated;
                    return authenticationResult ? "Login Succeeded"
                        : "Login Failed...Please try again";
                }
                else return "Failed to Initialize.";


            }).ObserveOn(SynchronizationContext.Current));

Need Your Help

Dynamic added div with onclick link

javascript onclick

I'm adding some amount of div based on the xml list which contain some data and url

Zend pdf, resizing and placing and a pdfstring to a pdf

php zend-framework pdf-generation zend-pdf

I have made good progress with producing pdf's with Zend PDF.