質問

フロントエンドにWCF net.tcpとWPFを使用してオンラインポーカーシステムを作成しました。うまく機能しますが、フロントエンドをシルバーライトに変換するときに改善できるものがいくつかあると思います。

私が仲間の建築家に持っている質問の1つは、ゲームロビーをどのようにリフレッシュすべきかということです。ポーカーゲームのロビーは、プレイヤー数、1時間あたりの手、フロップの割合などの統計で継続的に更新されます。

いつでも何百ものゲームが進行中である可能性があるため、5秒ごとにゲームのリスト全体を返す(投票)が最適であるかどうかはわかりません。多くのゲームにステータスの更新がないため、デルタクエリを使用することを考えていました(例:テーブルにプレーヤーはいません)。

私は更新時間を使用することを考えていたので、クライアント(数百または数千人であるかもしれない!)が投票するたびに、5、10、またはそれ以上の秒以内に更新された記録のみが返されます。

ゲームロビークライアントはもちろん、新しいデータの調整に責任を負いますが、これはゲームサーバーの負担の一部を緩和するのに役立つと思います。

何か案は?

役に立ちましたか?

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

他のヒント

周期的な更新のために、クライアントがサーバーに登録するアプローチを選択する場合があります。したがって、サーバーは、クライアントが実装する必要があるコールバック契約(デュプレックス契約)とのサービス契約を提供します。見る ここ 詳細については。

一方、Silverlightクライアントからの二重契約を使用することは難しいかもしれません(それが可能かどうかはまったくわかりません)ので、更新時間間隔でのポーリングは法的アプローチです。サーバーは、ポーリングサイクルの応答データと一緒に現在のタイムスタンプを送信する必要があります。クライアントは、更新されたデータが要求されたときから次のリクエストで送り返します。クライアントとサーバーの時間を比較しないでください。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top