Question

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));
        }
    }
Was it helpful?

Solution 3

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.

OTHER TIPS

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.

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));
        }
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top