diff --git a/ServerBrowser/ServerBrowserForm.Designer.cs b/ServerBrowser/ServerBrowserForm.Designer.cs index 13bee27..9df9820 100644 --- a/ServerBrowser/ServerBrowserForm.Designer.cs +++ b/ServerBrowser/ServerBrowserForm.Designer.cs @@ -96,6 +96,7 @@ private void InitializeComponent() this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); this.comboGames = new DevExpress.XtraEditors.ComboBoxEdit(); this.picLogo = new DevExpress.XtraEditors.PictureEdit(); + this.timerUpdateServerList = new System.Windows.Forms.Timer(this.components); ((System.ComponentModel.ISupportInitialize)(this.gcDetails)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.gvDetails)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.comboRegion.Properties)).BeginInit(); @@ -836,6 +837,12 @@ private void InitializeComponent() this.picLogo.Visible = false; this.picLogo.Click += new System.EventHandler(this.picLogo_Click); // + // timerUpdateServerList + // + this.timerUpdateServerList.Enabled = true; + this.timerUpdateServerList.Interval = 250; + this.timerUpdateServerList.Tick += new System.EventHandler(this.timerUpdateServerList_Tick); + // // ServerBrowserForm // this.Appearance.Options.UseFont = true; @@ -965,6 +972,7 @@ private void InitializeComponent() private ComboBoxEdit comboGames; private LabelControl labelControl4; private LabelControl labelControl5; + private System.Windows.Forms.Timer timerUpdateServerList; diff --git a/ServerBrowser/ServerBrowserForm.cs b/ServerBrowser/ServerBrowserForm.cs index c6124b3..54ef4c9 100644 --- a/ServerBrowser/ServerBrowserForm.cs +++ b/ServerBrowser/ServerBrowserForm.cs @@ -46,6 +46,9 @@ public partial class ServerBrowserForm : XtraForm private int ignoreUiEvents; private readonly CheckEdit[] favGameRadioButtons; private readonly List gameIdForComboBoxIndex = new List(); + private volatile bool serverListUpdateNeeded; + private const int maxResults = 500; + private volatile int currentRequestId; // logical clock to drop obsolete replies, e.g. when the user selected a different game in the meantime #region ctor() public ServerBrowserForm() @@ -334,15 +337,17 @@ private void UpdateServerList() IpFilter filter = new IpFilter(); filter.App = this.SteamAppID; var region = (QueryMaster.Region)steamRegions[this.comboRegion.SelectedIndex * 2 + 1]; - master.GetAddresses(region, endpoints => OnMasterServerReceive(endpoints, this.SteamAppID), filter); + + var requestId = ++this.currentRequestId; + master.GetAddresses(region, endpoints => OnMasterServerReceive(endpoints, requestId), filter); } #endregion #region OnMasterServerReceive() - private void OnMasterServerReceive(ReadOnlyCollection endPoints, Game queryAppId) + private void OnMasterServerReceive(ReadOnlyCollection endPoints, int requestId) { - // ignore results from older queries with a different appId - if (queryAppId != this.SteamAppID) + // ignore results from older queries + if (requestId != this.currentRequestId) return; string statusText; @@ -358,12 +363,12 @@ private void OnMasterServerReceive(ReadOnlyCollection endPoints, Gam if (ep.Address.Equals(IPAddress.Any)) { statusText = "Master server returned " + this.servers.Count + " servers"; - AllServersReceived(); + this.AllServersReceived(requestId); } - else if (servers.Count >= 1000) + else if (servers.Count >= maxResults) { - statusText = "Server list limited to 1000 entries"; - AllServersReceived(); + statusText = "Server list limited to " + maxResults + " entries"; + this.AllServersReceived(requestId); break; } else @@ -371,32 +376,36 @@ private void OnMasterServerReceive(ReadOnlyCollection endPoints, Gam } } + this.serverListUpdateNeeded = true; this.BeginInvoke((Action) (() => { - if (statusText != null) - this.txtStatus.Caption = statusText; - this.gvServers.BeginDataUpdate(); - this.gvServers.EndDataUpdate(); + this.txtStatus.Caption = statusText; })); } #endregion #region AllServersReceived() - private void AllServersReceived() + private void AllServersReceived(int requestId) { foreach (var row in this.servers) { var safeRow = row; - ThreadPool.QueueUserWorkItem(context => UpdateServerDetails(safeRow)); + ThreadPool.QueueUserWorkItem(context => UpdateServerDetails(safeRow, requestId)); } } #endregion #region UpdateServerDetails() - private void UpdateServerDetails(ServerRow row, Action callback = null) - { + private void UpdateServerDetails(ServerRow row, int requestId, Action callback = null) + { + if (requestId != this.currentRequestId) // drop obsolete requests + return; + Server server = ServerQuery.GetServerInstance(EngineType.Source, row.EndPoint, false, 500, 500); - string status = UpdateServerInfo(row, server) && UpdatePlayers(row, server) && UpdateRules(row, server) ? "ok" : "timeout"; + string status = UpdateServerInfo(row, server, requestId) && UpdatePlayers(row, server, requestId) && UpdateRules(row, server, requestId) ? "ok" : "timeout"; + if (requestId != this.currentRequestId) // status might have changed + return; + if (row.Retries > 0) status += " (" + row.Retries + ")"; row.Status = status; @@ -404,21 +413,20 @@ private void UpdateServerDetails(ServerRow row, Action callback = null) if (this.shutdown) return; - this.BeginInvoke((Action)(() => - { - this.gvServers.BeginDataUpdate(); - this.gvServers.EndDataUpdate(); - if (callback != null) - callback(); - })); + this.serverListUpdateNeeded = true; + if (callback != null) + this.BeginInvoke(callback); } #endregion #region UpdateServerInfo() - private bool UpdateServerInfo(ServerRow row, Server server) + private bool UpdateServerInfo(ServerRow row, Server server, int requestId) { for (row.Retries = 0; row.Retries < 3; row.Retries++) { + if (requestId != this.currentRequestId) + return false; + try { row.Status = "try " + (row.Retries + 1); @@ -432,8 +440,10 @@ private bool UpdateServerInfo(ServerRow row, Server server) #endregion #region UpdatePlayers() - private bool UpdatePlayers(ServerRow row, Server server) + private bool UpdatePlayers(ServerRow row, Server server, int requestId) { + if (requestId != this.currentRequestId) + return false; for (int attempt=0; attempt < 3; attempt++, row.Retries++) { try @@ -450,8 +460,10 @@ private bool UpdatePlayers(ServerRow row, Server server) #endregion #region UpdateRules() - private bool UpdateRules(ServerRow row, Server server) + private bool UpdateRules(ServerRow row, Server server, int requestId) { + if (requestId != this.currentRequestId) + return false; if (this.currentExtension != null && !this.currentExtension.SupportsRules) return true; @@ -604,7 +616,7 @@ private void gvServers_FocusedRowChanged(object sender, DevExpress.XtraGrid.View Application.DoEvents(); row.Status = "updating..."; ThreadPool.QueueUserWorkItem(dummy => - this.UpdateServerDetails(row, () => + this.UpdateServerDetails(row, this.currentRequestId, () => { if (this.gvServers.GetRow(this.gvServers.FocusedRowHandle) == row) this.UpdateGridDataSources(row); @@ -644,5 +656,16 @@ private void dockManager1_StartDocking(object sender, DockPanelCancelEventArgs e e.Cancel = true; } #endregion + + #region timerUpdateServerList_Tick + private void timerUpdateServerList_Tick(object sender, EventArgs e) + { + if (!this.serverListUpdateNeeded) + return; + this.serverListUpdateNeeded = false; + this.gvServers.BeginDataUpdate(); + this.gvServers.EndDataUpdate(); + } + #endregion } } \ No newline at end of file diff --git a/ServerBrowser/ServerBrowserForm.resx b/ServerBrowser/ServerBrowserForm.resx index 1af9e8e..9161d8a 100644 --- a/ServerBrowser/ServerBrowserForm.resx +++ b/ServerBrowser/ServerBrowserForm.resx @@ -132,4 +132,7 @@ 475, 17 + + 568, 17 + \ No newline at end of file