Question

I have created an online poker system using WCF net.tcp and WPF for the front end. It works great, but I feel there are some things I can improve upon when I convert the front end to Silverlight.

One of the questions I have for fellow architects is how should the game lobby be refreshed? A poker game lobby is continually updated with statistics like number of players, hands per hour, and flop percentage.

Since there could be hundreds of games in progress at any given time, I am not so sure that returning the entire list of games every 5 seconds (polling) is optimum. I was thinking of using a delta query since many games will not have status updates (e.g.: no players on the table).

I was thinking of using an update time so every time a client (which may be hundreds or even thousands!) poll, only the records updated within say 5, 10, or more seconds are returned.

The game lobby client will of course be responsible for reconciling the new data, but I think this could help relieve some of the burden on the game servers.

Any ideas?

Was it helpful?

Solution 2

<Window x:Class="TestListUpdate.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <Grid>
        <ListView Name="listView1">
            <ListView.View>
                <GridView>
                    <GridViewColumn Width="140" Header="Name" DisplayMemberBinding="{Binding Value.Name}" />
                    <GridViewColumn Width="140" Header="Creator" DisplayMemberBinding="{Binding Value.Creator}" />
                    <GridViewColumn Width="140" Header="Publisher" DisplayMemberBinding="{Binding Value.Publisher}" />
                </GridView>
            </ListView.View>
        </ListView>
    </Grid>
</Window>


namespace TestListUpdate
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        Dictionary<int, GameData> _gameData = null;

        // This is a test, real data will be retrieved via a web service
        List<GameData> _updates = null;

        public Window1()
        {
            InitializeComponent();

            // This is the original data bound to the ListView control
            this._gameData = new Dictionary<int, GameData>();
            this._gameData.Add(1, new GameData { Id = 1, Creator = "ABC", Name = "One", Publisher = "123" });
            this._gameData.Add(2, new GameData { Id = 2, Creator = "DEF", Name = "Two", Publisher = "456" });
            this._gameData.Add(3, new GameData { Id = 3, Creator = "GHI", Name = "Three", Publisher = "789" });
            this._gameData.Add(4, new GameData { Id = 4, Creator = "JKL", Name = "Four", Publisher = "abc" });
            this._gameData.Add(5, new GameData { Id = 5, Creator = "MNO", Name = "Five", Publisher = "def" });

            // This is test data, some Ids are duplicates of the original data above
            // other items represent new items
            this._updates = new List<GameData>();
            this._updates.Add(new GameData { Id = 2, Creator = "DDD", Name = "Two", Publisher = "123" });
            this._updates.Add(new GameData { Id = 3, Creator = "TTT", Name = "Three", Publisher = "456" });
            this._updates.Add(new GameData { Id = 5, Creator = "FFF", Name = "Five", Publisher = "789" });
            this._updates.Add(new GameData { Id = 6, Creator = "XXX", Name = "Six", Publisher = "abc" });
            this._updates.Add(new GameData { Id = 7, Creator = "VVV", Name = "Seven", Publisher = "def" });

            System.Windows.Threading.DispatcherTimer timer = new System.Windows.Threading.DispatcherTimer();
            timer.Interval = new TimeSpan(0, 0, 5);
            timer.Tick += new EventHandler(timer_Tick);
            timer.Start();
        }

        void timer_Tick(object sender, EventArgs e)
        {
            // Get a list of Ids from the new data
            var ids = (from l in this._updates
                       select l.Id);

            // Get a list of items that have matching Ids,
            // this data will be updated
            var updates = (from g in this._gameData
                           where ids.Contains(g.Value.Id)
                           select g);

            // Update the current items
            for (int i = 0; i < updates.Count(); ++i)
            {
                KeyValuePair<int, GameData> kvp = updates.ElementAt(i);
                kvp.Value.Publisher = DateTime.Now.ToLongTimeString();
            }

            // This represents new items to add
            this._gameData = this._gameData.Concat(
                    (from n in this._updates
                     where !this._gameData.ContainsKey(n.Id)
                     select n).ToDictionary(a => a.Id, a => a)
                 ).ToDictionary(q => q.Key, q => q.Value);

            // This is a simple trick to rebind the ListView control
            this.listView1.ItemsSource = null;
            this.listView1.ItemsSource = GameList;
        }

        // Databinding property
        public Dictionary<int, GameData> GameList
        {
            get { return this._gameData; }
        }
    }

    // Data class
    public class GameData
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Creator { get; set; }
        public string Publisher { get; set; }
    }
}

OTHER TIPS

You might choose an approach where the clients register at the server for cyclic updates. The server would therefore provide a service contract with a callback contract (a duplex contract) that the client would have to implement. See here for the details.

On the other hand it might be difficult to use a duplex contract from a Silverlight client (I'm not sure if it's possible at all), so polling with an update time interval is a legal approach. The server should send a current timestamp together with a polling cycle's response data, which the client would sent back with its next request to indicate since when updated data is requested. Avoid comparing client and server times.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top