Common Timer redraw
Common_TimerRedraw_VBNet\ThreadedUpdate.aspx.vb
' Copyright 2010 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.
' 

Imports Microsoft.VisualBasic
Imports System
Partial Public Class ThreadedUpdate
  Inherits System.Web.UI.Page
  #Region "Member Variables"

  ' Name of the resource to add graphics to
  Private _graphicsResourceName As String = "GraphicsResource"

  ' Amount of time to wait for the operation to complete when executing is initiated, in milliseconds
  Private _initialWaitTime As Integer = 2000

  ' Amount of time to add to the execution of retrieving new graphics, in milliseconds
  Private _simulatedOperationLength As Integer = 5000

  ' Key for session variable indicating whether graphics drawing is complete
  Private drawCompleteSessionKey As String = "DrawComplete"

  ' Array containing the names of the 48 contiguous states.  Used in creating feature graphics for a 
  ' random subset of these states.
  Private _states() As String = { "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" }

  #End Region

  #Region "Event Handlers - Page_Load, RequestReceived"

  Protected Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs)
    ' Initialize the session variable that indicates whether the current operation has completed
    If (Not Me.IsAsync) AndAlso Me.Session(drawCompleteSessionKey) Is Nothing Then
      Me.Session(drawCompleteSessionKey) = False
    End If
  End Sub

  Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
    ' 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.
    AddHandler PostbackManager1.RequestReceived, AddressOf PostbackManager1_RequestReceived
  End Sub

  ' Fires when a request is received that was initiated by a call to PostbackManager.doAsyncRequest on the client
    Private Sub PostbackManager1_RequestReceived(ByVal sender As Object, ByVal args As PostbackManager_VBNet.AdfRequestEventArgs)
        ' Parse the request arguments
        Dim requestArgs As System.Collections.Specialized.NameValueCollection = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackUtility.ParseStringIntoNameValueCollection(args.RequestArguments)

        ' Indicates whether the graphics resource needs to be refreshed
        Dim refreshGraphics As Boolean = False

        ' Check the event argument and draw or clear graphics accordingly
        Select Case requestArgs("EventArg")
            Case "DrawGraphics"
                ' Get the current time
                Dim startTime As System.DateTime = System.DateTime.Now

                ' Invoke the graphics drawing logic on a new thread
                Dim drawGraphicsCallback As New System.Threading.WaitCallback(AddressOf DrawGraphics)
                System.Threading.ThreadPool.QueueUserWorkItem(drawGraphicsCallback)

                ' Initialize a time span that will store the elapsed time since starting the operation
                Dim elapsedTime As System.TimeSpan = System.DateTime.Now.Subtract(startTime)

                ' Allow the draw graphics operation the amount of time to complete indicated by _initialWaitTime
                Do While elapsedTime.TotalMilliseconds < _initialWaitTime
                    ' Check whether the draw graphics operation is done
                    If CBool(Me.Session(drawCompleteSessionKey)) Then
                        ' The operation is complete, so the graphics resource needs to be refreshed
                        refreshGraphics = True
                        Exit Do
                    End If

                    ' Wait half a second before continuing the loop
                    System.Threading.Thread.Sleep(500)

                    ' Update the elapsed time
                    elapsedTime = System.DateTime.Now.Subtract(startTime)
                Loop
            Case "CheckGraphics"
                ' Check whether the draw graphics operation is complete and set the refreshGraphics flag accordingly
                If CBool(Me.Session(drawCompleteSessionKey)) Then
                    refreshGraphics = True
                End If
            Case "ClearGraphics"
                ' Call method to clear graphics and set the flag to refresh graphics
                ClearGraphics()
                refreshGraphics = True
        End Select

        If refreshGraphics Then
            ' 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.
            SyncLock Me.Session.SyncRoot
                Me.Session(drawCompleteSessionKey) = False
            End SyncLock

            ' 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") Then
                PostbackManager1.CustomResults = "cleared"
            Else
                PostbackManager1.CustomResults = "complete"
            End If
        Else
            PostbackManager1.CustomResults = "pending"
        End If
    End Sub

  #End Region

  #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 Sub DrawGraphics(ByVal o As Object)
    ' Get the graphics resource
    Dim graphicsMapFunctionality As ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapFunctionality = TryCast(Map1.GetFunctionality(_graphicsResourceName), 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
        Dim targetResourceName As String = "USA"
    Dim commonMapFunctionality As ESRI.ArcGIS.ADF.Web.DataSources.IMapFunctionality = Map1.GetFunctionality(targetResourceName)
    Dim queryFunctionality As ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality = CType(commonMapFunctionality.Resource.CreateFunctionality(GetType(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality), Nothing), ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality)

    ' Get the names and IDs of the layers in the resource that can be queried
    Dim layerIDs() As String
    Dim layerNames() As String
    queryFunctionality.GetQueryableLayers(Nothing, layerIDs, layerNames)

    ' Get the index of the states layer
    Dim targetLayerName As String = "States"
    Dim targetLayerID As String = Nothing
    For i As Integer = 0 To layerNames.Length - 1
      If layerNames(i).ToLower() = targetLayerName.ToLower() Then
        targetLayerID = layerIDs(i)
        Exit For
      End If
    Next i

    ' Initialize a filter for querying states
    Dim adfQueryFilter As New ESRI.ArcGIS.ADF.Web.QueryFilter()
    adfQueryFilter.ReturnADFGeometries = True
    adfQueryFilter.MaxRecords = 50

    ' Specify that only the STATE_NAME field be queried
    Dim targetFieldName As String = "STATE_NAME"
    Dim stringCollection As New ESRI.ArcGIS.ADF.StringCollection(targetFieldName, ","c)
    adfQueryFilter.SubFields = stringCollection

    Dim stringBuilder As New System.Text.StringBuilder()

    ' Generate the number of states to display graphics for
    Dim randomizer As New System.Random()
    Dim numberStates As Integer = randomizer.Next(4, 26)

    ' Get a state name from the list
    Dim stateName As String = _states(randomizer.Next(_states.Length))
    ' Add the number of unique state names specified by numberStates
    For i As Integer = 0 To numberStates - 1
      ' Get the list
      Dim stateList As String = stringBuilder.ToString()

      ' Keep picking random state names until one is picked that isn't already on the list
      Do While stateList.Contains(stateName)
        stateName = _states(randomizer.Next(_states.Length))
      Loop

      ' Add the state to the list
      stringBuilder.AppendFormat("'{0}',", stateName)
    Next i

    ' Remove the trailing comma from the list
    Dim whereClause As String = 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
    Dim resultsTable As System.Data.DataTable = queryFunctionality.Query(commonMapFunctionality.Name, targetLayerID, adfQueryFilter)

    ' Convert results to a graphics layer and add to the map
    Dim resultsGraphicsLayer As ESRI.ArcGIS.ADF.Web.Display.Graphics.GraphicsLayer = ESRI.ArcGIS.ADF.Web.UI.WebControls.Converter.ToGraphicsLayer(resultsTable)
    Dim layerName As String = "Feature Graphics"
    resultsGraphicsLayer.TableName = layerName

    ' Lock the map functionality while it is being modified to avoid thread contention
    SyncLock graphicsMapFunctionality
      If graphicsMapFunctionality.GraphicsDataSet.Tables.Contains(layerName) Then
        graphicsMapFunctionality.GraphicsDataSet.Tables.Remove(layerName)
      End If
      graphicsMapFunctionality.GraphicsDataSet.Tables.Add(resultsTable)
    End SyncLock

    ' Set the session flag indicating the operation is complete to true.  Lock the session while doing
    ' this to avoid thread contention.
    SyncLock Me.Session.SyncRoot
      Me.Session(drawCompleteSessionKey) = True
    End SyncLock
  End Sub

  ' Removes element or feature graphics from the map
  Private Sub ClearGraphics()
    ' Get the graphics resource
    Dim graphicsMapFunctionality As ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapFunctionality = TryCast(Map1.GetFunctionality(_graphicsResourceName), ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapFunctionality)

    ' Remove the element or feature graphics layer from the resource
    If graphicsMapFunctionality.GraphicsDataSet.Tables.Contains("Feature Graphics") Then
      graphicsMapFunctionality.GraphicsDataSet.Tables.Remove("Feature Graphics")
    End If
  End Sub

  #End Region
End Class