Common_TimerRedraw_CSharp\ThreadedUpdate.aspx.cs
// Copyright 2011 ESRI // // All rights reserved under the copyright laws of the United States // and applicable international laws, treaties, and conventions. // // You may freely redistribute and use this sample code, with or // without modification, provided you include the original copyright // notice and use restrictions. // // See the use restrictions. // public partial class ThreadedUpdate : System.Web.UI.Page { #region Member Variables // Name of the resource to add graphics to private string _graphicsResourceName = "GraphicsResource"; // Amount of time to wait for the operation to complete when executing is initiated, in milliseconds private int _initialWaitTime = 2000; // Amount of time to add to the execution of retrieving new graphics, in milliseconds private int _simulatedOperationLength = 5000; // Key for session variable indicating whether graphics drawing is complete private string drawCompleteSessionKey = "DrawComplete"; // Array containing the names of the 48 contiguous states. Used in creating feature graphics for a // random subset of these states. private string[] _states = { "Alabama","Arizona","Arkansas","California","Colorado","Connecticut", "Delaware","Florida","Georgia","Idaho","Illinois","Indiana","Iowa","Kansas","Kentucky","Louisiana", "Maine","Maryland","Massachusetts","Michigan","Minnesota","Mississippi","Missouri","Montana", "Nebraska","Nevada","New Hampshire","New Jersey","New Mexico","New York","North Carolina", "North Dakota","Ohio","Oklahoma","Oregon","Pennsylvania","Rhode Island","South Carolina","South Dakota", "Tennessee","Texas","Utah","Vermont","Virginia","Washington","West Virginia","Wisconsin","Wyoming" }; #endregion #region Event Handlers - Page_Load, RequestReceived protected void Page_PreRender(object sender, System.EventArgs e) { // Initialize the session variable that indicates whether the current operation has completed if (!this.IsAsync && this.Session[drawCompleteSessionKey] == null) this.Session[drawCompleteSessionKey] = false; } protected void Page_Load(object sender, System.EventArgs e) { // Add a handler for the PostbackManager's RequestReceived event. This event fires whenever doAsyncRequest // is called on on the client tier PostbackManager. For more information on the PostbackManager, see the // Common_PostbackManager sample. PostbackManager1.RequestReceived += new PostbackManager_CSharp.RequestReceivedEventHandler(PostbackManager1_RequestReceived); } // Fires when a request is received that was initiated by a call to PostbackManager.doAsyncRequest on the client void PostbackManager1_RequestReceived(object sender, PostbackManager_CSharp.AdfRequestEventArgs args) { // Parse the request arguments System.Collections.Specialized.NameValueCollection requestArgs = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackUtility.ParseStringIntoNameValueCollection(args.RequestArguments); // Indicates whether the graphics resource needs to be refreshed bool refreshGraphics = false; // Check the event argument and draw or clear graphics accordingly switch (requestArgs["EventArg"]) { case "DrawGraphics": // Get the current time System.DateTime startTime = System.DateTime.Now; // Invoke the graphics drawing logic on a new thread System.Threading.WaitCallback drawGraphicsCallback = new System.Threading.WaitCallback(DrawGraphics); System.Threading.ThreadPool.QueueUserWorkItem(drawGraphicsCallback); // Initialize a time span that will store the elapsed time since starting the operation System.TimeSpan elapsedTime = System.DateTime.Now - startTime; // Allow the draw graphics operation the amount of time to complete indicated by _initialWaitTime while (elapsedTime.TotalMilliseconds < _initialWaitTime) { // Check whether the draw graphics operation is done if ((bool)this.Session[drawCompleteSessionKey]) { // The operation is complete, so the graphics resource needs to be refreshed refreshGraphics = true; break; } // Wait half a second before continuing the loop System.Threading.Thread.Sleep(500); // Update the elapsed time elapsedTime = System.DateTime.Now - startTime; } break; case "CheckGraphics": // Check whether the draw graphics operation is complete and set the refreshGraphics flag accordingly if ((bool)this.Session[drawCompleteSessionKey]) refreshGraphics = true; break; case "ClearGraphics": // Call method to clear graphics and set the flag to refresh graphics ClearGraphics(); refreshGraphics = true; break; } if (refreshGraphics) { // Apply the graphics updates to the map Map1.RefreshResource(_graphicsResourceName); PostbackManager1.CallbackResults.CopyFrom(Map1.CallbackResults); // Reset the session variable. We do this in a lock to avoid thread contention. lock (this.Session.SyncRoot) this.Session[drawCompleteSessionKey] = false; // Set the postback manager's custom results. These will be used on the client to determine // whether to set an update graphics timeout and to update the status text. if (requestArgs["EventArg"].Contains("Clear")) PostbackManager1.CustomResults = "cleared"; else PostbackManager1.CustomResults = "complete"; } else { PostbackManager1.CustomResults = "pending"; } } #endregion #region Private Graphics Manipulation Methods - DrawGraphics, ClearGraphics // Draws a random subset of states as feature graphics on the map. The object parameter is included so the // method can be used to create a WaitCallback. private void DrawGraphics(object o) { // Get the graphics resource ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapFunctionality graphicsMapFunctionality = Map1.GetFunctionality(_graphicsResourceName) as ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapFunctionality; // Suspend the thread for the specified simulation duration System.Threading.Thread.Sleep(_simulatedOperationLength); // Get a query functionality for the USA_Data resource string targetResourceName = "USA"; ESRI.ArcGIS.ADF.Web.DataSources.IMapFunctionality commonMapFunctionality = Map1.GetFunctionality(targetResourceName); ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality queryFunctionality = (ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality)commonMapFunctionality.Resource.CreateFunctionality( typeof(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality), null); // Get the names and IDs of the layers in the resource that can be queried string[] layerIDs; string[] layerNames; queryFunctionality.GetQueryableLayers(null, out layerIDs, out layerNames); // Get the index of the states layer string targetLayerName = "States"; string targetLayerID = null; for (int i = 0; i < layerNames.Length; i++) { if (layerNames[i].ToLower() == targetLayerName.ToLower()) { targetLayerID = layerIDs[i]; break; } } // Initialize a filter for querying states ESRI.ArcGIS.ADF.Web.QueryFilter adfQueryFilter = new ESRI.ArcGIS.ADF.Web.QueryFilter(); adfQueryFilter.ReturnADFGeometries = true; adfQueryFilter.MaxRecords = 50; // Specify that only the STATE_NAME field be queried string targetFieldName = "STATE_NAME"; ESRI.ArcGIS.ADF.StringCollection stringCollection = new ESRI.ArcGIS.ADF.StringCollection(targetFieldName, ','); adfQueryFilter.SubFields = stringCollection; System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder(); // Generate the number of states to display graphics for System.Random randomizer = new System.Random(); int numberStates = randomizer.Next(4, 26); // Get a state name from the list string stateName = _states[randomizer.Next(_states.Length)]; // Add the number of unique state names specified by numberStates for (int i = 0; i < numberStates; i++) { // Get the list string stateList = stringBuilder.ToString(); // Keep picking random state names until one is picked that isn't already on the list while (stateList.Contains(stateName)) stateName = _states[randomizer.Next(_states.Length)]; // Add the state to the list stringBuilder.AppendFormat("'{0}',", stateName); } // Remove the trailing comma from the list string whereClause = stringBuilder.ToString(); whereClause = whereClause.Substring(0, whereClause.Length - 1); // Specify that the query filter get features that match the states in the list adfQueryFilter.WhereClause = string.Format("STATE_NAME IN ({0})", whereClause); // Execute the query System.Data.DataTable resultsTable = queryFunctionality.Query( commonMapFunctionality.Name, targetLayerID, adfQueryFilter); // Convert results to a graphics layer and add to the map ESRI.ArcGIS.ADF.Web.Display.Graphics.GraphicsLayer resultsGraphicsLayer = ESRI.ArcGIS.ADF.Web.UI.WebControls.Converter.ToGraphicsLayer(resultsTable); string layerName = "Feature Graphics"; resultsGraphicsLayer.TableName = layerName; // Lock the map functionality while it is being modified to avoid thread contention lock (graphicsMapFunctionality) { if (graphicsMapFunctionality.GraphicsDataSet.Tables.Contains(layerName)) graphicsMapFunctionality.GraphicsDataSet.Tables.Remove(layerName); graphicsMapFunctionality.GraphicsDataSet.Tables.Add(resultsTable); } // Set the session flag indicating the operation is complete to true. Lock the session while doing // this to avoid thread contention. lock (this.Session.SyncRoot) this.Session[drawCompleteSessionKey] = true; } // Removes element or feature graphics from the map private void ClearGraphics() { // Get the graphics resource ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapFunctionality graphicsMapFunctionality = Map1.GetFunctionality(_graphicsResourceName) as ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapFunctionality; // Remove the element or feature graphics layer from the resource if (graphicsMapFunctionality.GraphicsDataSet.Tables.Contains("Feature Graphics")) graphicsMapFunctionality.GraphicsDataSet.Tables.Remove("Feature Graphics"); } #endregion }