2009-12-23 13 views
3

J'essaie d'utiliser .NET Reactive Framework pour simplifier certains appels asynchrones à un service WCF utilisé par une application Silverlight 3 que j'écris. Le problème est que j'ai du mal à trouver un moyen de structurer mon code d'une manière qui fonctionnera. Une partie du problème, sans aucun doute, est de comprendre quels mécanismes sont disponibles dans Réactif et comment les utiliser pour résoudre mon problème.Utilisation de Observable.FromEvent lors de l'appel d'un service WCF dans Silverlight

Je suis en train d'enchaîner une série d'appels de serveur WCF - si elles étaient synchrones, ils ressemblent à ceci:

switch(CurrentVisualState) 
{ 
    case GameVisualState.Welcome: 
     m_gameState = m_Server.StartGame(); 
     if(m_GameState.Bankroll < Game.MinimumBet) 
      NotifyPlayer(...); // some UI code here ... 
     goto case GameVisualState.HandNotStarted; 

    case GameVisualState.HandNotStarted: 
    case GameVisualState.HandCompleted: 
    case GameVisualState.HandSurrendered: 
     UpdateUIMechanics(); 
     ChangeVisualState(GameVisualState.HandPlaceBet); 
     break; 

    case GameVisualState.HandPlaceBet: 
     UpdateUIMechanics(); 
     // request updated game state from game server... 
     m_GameState = m_Server.NextHand(m_GameState, CurrentBetAmount); 
     if(CertainConditionInGameState(m_GameState)) 
      m_GameState = m_Server.CompleteHand(m_GameState); 
     break; 
} 

Les appels à m_Server.XXXX() utilisés pour être directement mis en œuvre dans l'application Silveright (ils peuvent donc être synchrones) - mais sont maintenant implémentés dans un service WCF. Comme Silverlight vous oblige à appeler les services WCF de manière asynchrone, il a été difficile de réécrire ce bloc de code.

J'espérais utiliser Observable.FromEvent<>() pour m'abonner aux divers événements XXXCompleted générés par le code du proxy WCF, mais je ne vois pas comment cela fonctionnera. Ma tentative originale ressemblait à quelque chose comme:

var startObs = Observable.FromEvent<StartGameCompletedEventArgs>(
        h => m_Server.StartGameCompleted += h, 
        h => m_Server.StartGameCompleted -= h); 

startObs.Subscribe(e => { m_gameState = e.EventArgs.Result.StartGameResult; 
          if(m_GameState.Bankroll < Game.MinimumBet) 
           NotifyPlayer(...); // some UI code here ... 
          TransitionVisual(GameVisualState.HandNotStarted); 
         }); // above code never reached... 

m_Server.StartGameAsync(); // never returns, but the WCF service is called 

Répondre

3

J'ai été capable de comprendre comment faire fonctionner ceci. Je poste cette réponse dans l'intérêt de partager ce que j'ai appris.

Il s'avère que la décision sur le thread sur lequel s'exécuter un observateur souscrit est très importante lors du traitement des appels WCF Silverlight. Dans mon cas, je devais m'assurer que le code souscrit s'exécutait sur le thread UI - ce qui a été accompli par le changement suivant:

var startObs = Observable.FromEvent<StartGameCompletedEventArgs>(
        h => m_Server.StartGameCompleted += h, 
        h => m_Server.StartGameCompleted -= h) 
     .Take(1) // necessary to ensure the observable unsubscribes 
     .ObserveOnDispatcher(); // controls which thread the observer runs on 

startObs.Subscribe(e => { m_gameState = e.EventArgs.Result.StartGameResult; 
          if(m_GameState.Bankroll < Game.MinimumBet) 
           NotifyPlayer(...); // some UI code here ... 
          TransitionVisual(GameVisualState.HandNotStarted); 
         }); // this code now executes with access to the UI 

m_Server.StartGameAsync(); // initiates the call to the WCF service