我正在尝试使用ReactiveUI命令进行WCF调用,并使用ObservableAsPropertyHelper捕获结果字符串。使用下面的代码我收到以下错误消息 -
“调用线程无法访问此对象,因为其他线程拥有它”
WCF调用返回但访问ObservableForProperty时出错 - 消息和/或提升其PropertyChanged
如果有人需要其他详细信息/代码,请告诉我。
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 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);
}
}
}
}
答案 0 :(得分:0)
您的大多数代码都是正确的(除了您设置message
的位置,只使用loggedIn.ToProperty
),但我记得,WCF试图通过摆弄SynchronizationContexts来“帮助您”,您需要禁用此功能(我不知道该怎么做)
答案 1 :(得分:0)
更新:通过告诉观察者回调在当前同步上下文上运行来修复。
<强> .ObserveOn(SynchronizationContext.Current)强>
以下是解决上述问题的LoginCommand Observable代码。最后一行是编辑。
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));