2014-01-31 47 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