Frage

Ich versuche, den .NET-Reactive Framework zu verwenden, um einige asynchronen Aufrufe zu einem WCF-Dienst von einem Silverlight 3 App verwendet zu vereinfachen, dass ich schreibe.

Das Problem ist, dass ich eine harte Zeit habe, einen Weg zu finden, meinen Code in einer Weise zu strukturieren, die funktionieren wird. Ein Teil des Problems, kein Zweifel, ist das Verständnis, welche Mechanismen sind in Reactive und wie sie verwenden, um mein Problem zu lösen.

Ich bin aneinanderzureihen eine Reihe von WCF-Server Anrufen versuchen - wenn sie synchron waren, sie in etwa so aussehen:

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

Die Aufrufe von m_Server.XXXX() verwendet innerhalb der Silveright App direkt umgesetzt werden (so könnten sie synchron sein) - aber jetzt sind in einem WCF-Dienst implementiert. Da Silverlight zwingt Sie WCF-Dienste asynchron zu nennen - Umschreiben dieser Code-Block ist heikel gewesen

.

Ich habe gehofft, Observable.FromEvent<>() zu verwenden, um die verschiedene XXXCompleted Ereignisse zu abonnieren, dass der WCF-Proxy-Code generiert, aber es ist mir nicht klar, wie diese zur Arbeit zu kommen. Mein ursprünglicher Versuch sah so etwas wie:

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
War es hilfreich?

Lösung

Ich war in der Lage, herauszufinden, wie diese zur Arbeit zu kommen. Ich veröffentliche diese Antwort im Interesse teilen, was ich gelernt habe.

Es stellt sich heraus, dass die Entscheidung, welche Thread einen abonnierten Beobachter auszuführen auf sehr wichtig ist, wenn sie mit Silverlight WCF Anrufe. In meinem Fall musste ich, dass die abonnierten Code läuft auf dem UI-Thread, um sicherzustellen, - die durch die folgende Änderung durchgeführt wurde:

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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top