2014-01-31 21 views
0

我正在尝试使用ReactiveUI命令进行WCF调用并使用ObservableAsPropertyHelper捕获结果字符串。下面我收到以下错误消息的代码 -WCF的ReactiveUI命令导致更新Observable属性时出现线程错误

WCF调用的回报,但在访问ObservableForProperty错误“调用线程不能因为不同的线程拥有它访问这个对象” - 消息和/或当提高其PropertyChanged

让我知道是否有人需要其他细节/代码。

视图模型:UserService.Authenticate是

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

      }); 

视图代码后面到WCF端点代理电话:

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

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

.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)); 
0

大部分代码是正确的(除了您设置的地方message,只需使用loggedIn.ToProperty),但我记得,WCF试图通过摆脱SynchronizationContexts“帮助你”,你需要禁用这个(我不知道如何做到这一点虽然)

+0

我添加[ServiceBehavior(UseSynchronizationContext = FALSE)] [CallbackBehavior(UseSynchronizationContext = FALSE)]我的服务类,但这并没有帮助 - 在它给我相同的结果。需要注意的是,当我使用方法存根替换验证呼叫时,这是有效的 - 所以保罗你是正确的,因为它与WCF有关 – denmerc

+0

您对ToProperty的建议是否与常规属性一起工作还是需要支持域需要成为一个ObservableAsPropertyHelper 消息它工作?在第一遍时,即使设置初始值参数像这样 - > loggedIn.ToProperty(this,x => x.Message,string.Empty); – denmerc

+0

另一个观察是如果成功验证并路由到MainView - 我得到{“调用线程必须是STA,因为许多UI组件需要这个。”}不知何故,我因为WCF而被抛出当前上下文 - 我是否留下来在LoginView上或导航到另一个视图? – denmerc