Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/wcf/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
带有WCF的ReactiveUI命令在更新可观察属性时导致线程错误_Wcf_Reactiveui - Fatal编程技术网

带有WCF的ReactiveUI命令在更新可观察属性时导致线程错误

带有WCF的ReactiveUI命令在更新可观察属性时导致线程错误,wcf,reactiveui,Wcf,Reactiveui,我试图使用ReactiveUI命令进行WCF调用,并使用ObservablesPropertyHelper捕获结果字符串。使用下面的代码,我收到以下错误消息- “调用线程无法访问此对象,因为其他线程拥有它” WCF调用在访问ObservableForProperty-消息和/或提升其属性更改时返回错误 如果有人需要其他详细信息/代码,请告诉我 ViewModel:UserService.Authenticate是对WCF端点的代理调用 public class LoginViewModel :

我试图使用ReactiveUI命令进行WCF调用,并使用ObservablesPropertyHelper捕获结果字符串。使用下面的代码,我收到以下错误消息-

“调用线程无法访问此对象,因为其他线程拥有它”

WCF调用在访问ObservableForProperty-消息和/或提升其属性更改时返回错误

如果有人需要其他详细信息/代码,请告诉我

ViewModel:UserService.Authenticate是对WCF端点的代理调用

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");

            });
public类LoginViewModel:ReactiveObject,IRoutableViewModel
{
公共登录视图模型(IScreen hostScreen、主视图模型ApprotViewModel、IUserService用户服务)
{
主机屏幕=主机屏幕;
UserService=UserService;
应用程序=ApprotViewModel;
var canLogin=this.WhenAny(x=>x.LoginName,x=>x.Password,(l,p)=>
!String.IsNullOrWhiteSpace(l.Value)和&!String.IsNullOrWhiteSpace(p.Value));
LoginCommand=newreactivecommand(canLogin);
var loggedIn=LoginCommand.RegisterAsync(=>Observable.Start(()=>
{
var请求=新请求
{
UserIdentity=新用户.Identity
{
Login=LoginName,
密码=新用户。密码{Old=Password}
}
};
var authenticationResult=UserService.Authenticate(请求).Authenticated;
返回authenticationResult?“登录成功…继续”
:“登录失败…请重试”;
}));
loggedIn.Subscribe(s=>
{
如果(s==“登录成功…继续分析”)
{
HostScreen.Router.Navigate.Execute(应用程序);
}
});
消息=新的ObservablesPropertyHelper(loggedIn,
s=>
{
raisePropertyChanged(“消息”);
});
查看隐藏代码

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);
        }
    }

}
public分部类LoginView:IViewFor
{
公共登录视图()
{
初始化组件();
this.whenyValue(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);
这个.OneWayBind(ViewModel,model=>model.Message,x=>x.Message.Content);
这个.OneWayBind(ViewModel,x=>x.LoginCommand,x=>x.login.Command);
}
公共静态只读从属属性ViewModelProperty=
DependencyProperty.Register(“ViewModel”、typeof(LoginView模型)、typeof(LoginView)、new PropertyMetadata(null));
对象IViewFor.ViewModel
{
获取{return ViewModel;}
设置{ViewModel=(LoginViewModel)值;}
}
公共登录视图模型视图模型
{
得到
{
返回(LoginViewModel)GetValue(ViewModelProperty);
}
设置
{
SetValue(ViewModelProperty,
价值);
}
}
}

}

您的大多数代码都是正确的(除了设置
消息的地方,只需使用
loggedIn.ToProperty
),但我记得,WCF试图通过摆弄SynchronizationContext来“帮助您”,您需要禁用它(但我不确定如何做到这一点)

更新:通过告诉观察者回调在当前同步上下文上运行来修复

.ObserveOn(SynchronizationContext.Current)

下面是解决上述问题的LoginCommand可观察代码。最后一行是编辑

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));
var loggedIn=LoginCommand.RegisterAsync(=>Observable.Start(()=>
{
会话初始化=新会话
{
SqlKey=System.Configuration.ConfigurationManager.AppSettings[“sharedKey”].ToString()
};
var initResponse=UserService.Initialize(init);
var authenticationResult=false;
if(initResponse.SessionOk)
{
initResponse.UserIdentity=新用户.Identity
{
Login=LoginName,
密码=新用户。密码{Old=Password}
};
authenticationResult=UserService.Authenticate(initResponse).Authenticated;
返回authenticationResult?“登录成功”
:“登录失败…请重试”;
}
否则返回“初始化失败。”;
}).ObserveOn(SynchronizationContext.Current));

我添加了[ServiceBehavior(UseSynchronizationContext=false)][CallbackBehavior(UseSynchronizationContext=false)]这对我的服务类没有帮助,因为它给了我相同的结果。需要注意的是,当我用一个方法存根替换身份验证调用时,这是有效的-因此Paul您是正确的,因为它与WCFalso有关。那么您关于TopProperty的建议是否适用于常规属性,或者是否需要使用支持字段ObservablesPropertyHelper消息是否有效?在第一次传递时,即使设置初始值param,如-->loggedIn.ToProperty(this,x=>x.message,string.Empty),消息上仍会出现null异常;另一个观察结果是,如果成功验证并路由到MainView,则返回-I get{“调用线程必须是STA,因为许多UI组件都需要它。”}不知何故,由于WCF,我被抛出了当前上下文-我是停留在LoginView还是导航到另一个视图?