0

I'm designing a silverlight game and I'm stuck with the game end functions. It's a turn based card game and I'm using WCF Duplex. But when I call finalize function, callbacks are receiving OnEndGame message before the OnFinalized message. I need that to play some animations in client before starting a new game. I tried many things inlcuding Thread.Sleep and Task.Wait etc. but I couldn't figure out the problem. What should I do to give some time for EndGame method to return?

    private void FinalizeGame()
    {
        this.GameState = Enums.GameState.Finalize;

        Task.Factory.StartNew(()=>{
            CalculateWinners();
            GameSubscriptionManager.Publish(SubscriptionType.GameStream, cb => cb.OnFinalize(this));
        }).ContinueWith((antecedent)=>{
            EndGame();
        });
    }

    private void EndGame()
    {
        this.GameState = Enums.GameState.None;

        Thread.Sleep(5000);

        GameSubscriptionManager.Publish(cb => cb.OnEndGame(this));
        RemovePlayersAndGetWaitingPlayers();


        if (PlayingPlayers.Count > 1)
        {
            ResetGame();
            StartGame();
        }
        else
        {
            GameState = GameState.None;
            GameSubscriptionManager.Publish(cb => cb.OnWaitingForNewPlayers(this));
        }
    }
Kubi
  • 2,139
  • 6
  • 35
  • 62
  • Where is called `Finalize` method and where is method itself? – sll Dec 17 '12 at 11:20
  • it's the final stage of the game where the game result is calculated and new game should begin. Finalize method is called at service to send OnFinalize to callbacks – Kubi Dec 17 '12 at 11:49

3 Answers3

1

I've never used WCF, but I believe you need to enable WS-ReliableMessaging if you want messages to arrive in-order. Try reading this. Good luck.

TaskEx.Delay is far better than Thread.Sleep, but either one is very fishy as a solution to (almost) any problem.

Aleksandr Dubinsky
  • 22,436
  • 15
  • 82
  • 99
  • thanks for the help Aleksandir. I'm getting an error in Fiddler (is not supported by this endpoint. Only WS-ReliableMessaging February 2005 messages are processed by this endpoint.?????) when I put reliableSession to my service. The config files are not matching probably.I'm on it now – Kubi Dec 18 '12 at 10:28
0

You can try to await in an asynchronous fashion. Grab the async target pack for Silverlight with VS2012 or VS2010. You can then use TaskEx.Delay as a replace for Thread.Sleep:

    private async Task EndGame()
    {
        this.GameState = Enums.GameState.None;

        await TaskEx.Delay(5000);

        GameSubscriptionManager.Publish(cb => cb.OnEndGame(this));
        RemovePlayersAndGetWaitingPlayers();


        if (PlayingPlayers.Count > 1)
        {
            ResetGame();
            StartGame();
        }
        else
        {
            GameState = GameState.None;
            GameSubscriptionManager.Publish(cb => cb.OnWaitingForNewPlayers(this));
        }
    }
Arthur Nunes
  • 6,718
  • 7
  • 33
  • 46
0

OK. Since none of threading or tasking worked out for my case, I decided to make a little trick and use an animation to occupy UI thread and use its completed event handler to make the delay function for my application.

I made the following extension for the dispatcher first,

public static class Extensions
{
    public static event EventHandler OnCompleted;

    public static void WaitForFakeAnimation(this Dispatcher dispatcher, TimeSpan timeToWait, EventHandler onCompleted)
    {
        Storyboard sb = new Storyboard();
        sb.Duration = timeToWait;
        OnCompleted += onCompleted;
        sb.Completed += (s,e) => 
        {
            OnCompleted(sb, null);
            OnCompleted -= onCompleted;

        };
        sb.Begin();
    }

}

I'm calling this from my GameManager class (which could be considered as a ViewModel)

        EventHandler aferAnimation = (s,e) => {
            lock (syncServiceUpdate)
            {
                AddNotification(notification);
                // MessageBox.Show("after wait");

            };
        };
        this.gamePage.Dispatcher.WaitForFakeAnimation(TimeSpan.FromSeconds(15), aferAnimation );

I would maybe send an ref Action to the extension as well but currently this solved my problem.

I hope this helps others as well.

Kubi
  • 2,139
  • 6
  • 35
  • 62