Geoprocessing task

The Geoprocessing task allows you to perform geoprocessing in your ArcGIS API for Windows Phone applications by executing geoprocessing models that you have created with ArcGIS. Geoprocessing models chain together GIS analysis operations so that they can be executed in an automated way. These models generally consists of a series of tools you might see in ESRI's ArcToolbox, chained together logically to accomplish a specific task. For example, a model might interpolate an elevation surface from a set of input spot heights, then create contours from that surface. Instead of manually opening two different tools from ArcToolbox, you just run the model. If you need to do this operation on 100 datasets, you can automate the model to run 100 times. This makes geoprocessing both powerful and convenient.

The Geoprocessor class in the ArcGIS API for Windows Phone gives you access to geoprocessing models that have been published to ArcGIS Server as geoprocessing services. These services are useful because geoprocessing can be computationally intensive and requires GIS software to run the tools and models. It's often more efficient to send geoprocessing jobs to a centralized server instead of relying on the processing power of client machines to perform the analysis. It can also be impractical to implement geoprocessing logic within your web application or to expect users to install extra software.

Creating a Geoprocessing task

As with all the tasks, you will initialize, execute, and process the results of the Geoprocessing task in your Windows Phone application's .NET code (i.e. code-behind). The Geoprocessing task does not contain any visual components, so it cannot be interacted with via XAML. This topic works with the Geoprocessing task in .NET code, assuming that the input and output interfaces are already defined. Typically, the task's input and output interfaces would be defined primarily in XAML. For instance, you might use a Map and a button that initialized a Draw object to accept input points, and then use a GraphicsLayer and InfoWindow to display the geoprocessing output. For step-by-step implementation of similar input/output interfaces, see the Find task, Query task, and Identify task topics. For examples of geoprocessing applications, complete with input and output interfaces, see the GP section of the Interactive SDK.

This topic covers the following geoprocessing task steps:

  1. Gathering service information
  2. Initializing the task
  3. Specifying the Geoprocessing task's input parameters
  4. Using the Geoprocessing task—Executing the task and handling the results
    1. Using a synchronous geoprocessing service
    2. Using an asynchronous geoprocessing service

Gathering service information

Before you can use the Geoprocessing task, you need to have three pieces of information about the geoprocessing service you wish to use:

  • The URL of the service
  • The required inputs and outputs of the task
  • Whether the task is asynchronous or synchronous

You can discover all of the above items in the ArcGIS Services Directory, which is a browseable depiction of what's available on an ArcGIS Server. The URL for the Services Directory is http://<server name>/<instance name>/rest/services. Refer to the Discovering services topic for general information about how to use Services Directory.

A Services Directory page for a geoprocessing task is shown below. When you navigate to this page, the URL to of the service will be displayed in the browser's address bar. The Execution Type shows whether the task is synchronous (esriExecutionTypeSynchronous) or asynchronous (esriExecutionTypeAsynchronous). For each parameter, you will need to know the parameter's name, data type, and whether it is used for input or returned as output. This information is circled in the figure below. The Data Types shown for the parameters match the classes you will use when initializing parameters in your code. Input parameters have a direction of esriGPParameterDirectionInput, while output parameters have a direction of esriGPParameterDirectionOutput.

GP Services Directory

Initializing the task

To initialize a Geoprocessing task, simply declare a Geoprocessor object, instantiate it with the new keyword, and pass the URL of the geoprocessing service's REST endpoint to the constructor:

Geoprocessor geoprocessorTask = new Geoprocessor("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/" + 
    "Specialty/ESRI_Currents_World/GPServer/MessageInABottle");

Specifying the Geoprocessing task's input parameters

The Geoprocessing task's execution methods take a list of GPParameter objects as input. All the geoprocessing parameter classes (e.g. GPFeatureRecordSetLayer, GPDouble, GPRecordSet, GPRasterData, etc.) derive from this class. The MessageInABottle service, shown in the Services Directory figure above, has two input parameters—Input_Point, which is of type GPFeatureRecordSetLayer, and Days, which is of type GPDouble. This code assumes that there is a MapPoint in the current scope named MyMapPoint, as well as a TextBox named DaysTextBox, that are used for input in the application.

List<GPParameter> parameters = new List<GPParameter>();
    parameters.Add(new GPFeatureRecordSetLayer("Input_Point", MyMapPoint));
    parameters.Add(new GPDouble("Days", Convert.ToDouble(DaysTextBox.Text)));

Using the Geoprocessing task

There are two sets of members for executing and handling the results of a Geoprocessing task. Which members you will use depends on whether the geoprocessing service executes synchronously or asynchronously. In ArcGIS Server, synchronous geoprocessing services return the results of each operation to the client as soon as the operation is complete - no results are stored on the server. Alternatively, asynchronous services store results on the server and return a job ID to the client. The client can then use this ID to retrieve the results at a convenient time. Synchronous services are intended for geoprocessing operations that take a short amount of time to execute (e.g. less than 3 seconds), while asynchronous services should be used for longer-running operations.

Using a synchronous geoprocessing service

When using a service that executes synchronously, you initiate the operation using the ExecuteAsync method. To retrieve results, you can either specify a handler for the ExecuteCompleted event or use the ExecuteLastResult property. In this example, the ExecuteCompleted handler is used. The following code attaches the handler to the task:

geoprocessorTask.ExecuteCompleted += GeoprocessorTask_ExecuteCompleted;

The ExecuteCompleted event handler is then implemented. Here it loops through the results features, adding each to a GraphicsLayer. Notice that each GPParameter in the results that are passed to the handler is assumed to be a GPFeatureRecordSetLayer object since this is the output type listed in the service's information page. The code assumes that a Map named MyMap containing a GraphicsLayer with an ID of MyGraphicsLayer and a Symbol named PathLineSymbol have been created and are available to the handler.

private void GeoprocessorTask_ExecuteCompleted(object sender, GPExecuteCompleteEventArgs e)
{
    GraphicsLayer graphicsLayer = MyMap.Layers["MyGraphicsLayer"] as GraphicsLayer;

    foreach (GPParameter gpParameter in e.Results.OutParameters)
    {
        GPFeatureRecordSetLayer gpLayer = gpParameter as GPFeatureRecordSetLayer;
        foreach (Graphic graphic in gpLayer.FeatureSet.Features)
        {
            graphic.Symbol = graphic.Symbol = LayoutRoot.Resources["PathLineSymbol"] as Symbol;
            graphicsLayer.Graphics.Add(graphic);
        }
    }
}

After the ExecuteCompleted handler is attached, the task can be executed using the ExecuteAsync method and passing in the parameters defined in the previous section.

geoprocessorTask.ExecuteAsync(parameters);

Using an asynchronous geoprocessing service

As explained above, when a client initiates an operation on an asynchronous geoprocessing service, the service returns a job ID to the client, which can then be used to retrieve the operation's results. The results are not automatically returned to the client when the operation is completed, but rather are stored on the server and are sent to the client only when the client requests them. Accordingly, you initiate an operation on an asynchronous geoprocessing service by calling the Geoprocessing task's SubmitJobAsync method, rather than ExecuteAsync:

geoprocessorTask.SubmitJobAsync(parameters);
NoteNote:

The code in this section is based on using the asynchronous service available at http://sampleserver2.arcgisonline.com/ArcGIS/rest/services/PublicSafety/EMModels/GPServer/ERGByChemical:

Geoprocessor geoprocessorTask = new Geoprocessor("http://sampleserver2.arcgisonline.com/ArcGIS/" +
    "rest/services/PublicSafety/EMModels/GPServer/ERGByChemical");
List<GPParameter> parameters = new List<GPParameter>();
    parameters.Add(new GPFeatureRecordSetLayer("Incident_Point", e.MapPoint));

Of course, a job's results can only be retrieved after the operation has completed. Asynchronous geoprocessing services do not notify the client when a job is complete, so it is up to the client to check with the service to determine the status of the job. By default, the ArcGIS API for Windows Phone does this for you automatically and fires the Geoprocessing task's JobCompleted event once an operation is done executing. A handler for JobCompleted is typically where you will request an asynchronous operation's results. The following code attaches the handler to the task:

geoprocessorTask.JobCompleted += GeoprocessorTask_JobCompleted;

For getting the results from an asynchronous Geoprocessing task, the task defines three different methods, each of which returns the results in a different format:

  • GetResultDataAsync—retrieves a collection of objects that expose all the result data (e.g. a collection of Graphics containing geometry and attributes)
  • GetResultImageLayerAsync—retrieves a GPResultImageLayer. This can be used to display the results by adding it directly to the Map, but does not contain information about individual results.
  • GetResultImageAsync—retrieves a GPResultImage, which contains a MapImage with the geometry of the results.

Each method requires you to specify the operation's job ID and the name of the output parameter to retrieve. For each, the results are passed to an event of the form <operation name>Completed (e.g. GetResultImageCompleted) and a property of the form <operation name>LastResult (e.g. GetResultImageLastResult) as soon as they are returned to the client. The code below demonstrates use of JobCompleted, GetResultDataAsync, and GetResultDataCompleted. The code for JobCompleted requests data for an output parameter called outerg_shp. In GetResultDataCompleted, it is assumed that:

  • There is a Map named MyMap
  • The Map contains a GraphicsLayer with the ID MyResultGraphicsLayer
  • A symbol named DefaultFillSymbol has been created
  • The output parameters are of type GPFeatureRecordSetLayer

The GetResultDataCompleted handler shown below simply iterates through the results features, adding each to a GraphicsLayer.

private void GeoprocessorTask_JobCompleted(object sender, JobInfoEventArgs e)
{
    Geoprocessor geoprocessorTask = sender as Geoprocessor;
    geoprocessorTask.GetResultDataCompleted += GeoprocessorTask_GetResultDataCompleted;
    geoprocessorTask.GetResultDataAsync(e.JobInfo.JobId, "outerg_shp");
}

private void GeoprocessorTask_GetResultDataCompleted(object sender, GPParameterEventArgs e)
{
    GraphicsLayer graphicsLayer = MyMap.Layers["MyResultGraphicsLayer"] as GraphicsLayer;

    GPFeatureRecordSetLayer gpLayer = e.Parameter as GPFeatureRecordSetLayer;
    foreach (Graphic graphic in gpLayer.FeatureSet.Features)
    {
        graphic.Symbol = LayoutRoot.Resources["DefaultFillSymbol"] as Symbol;
        graphicsLayer.Graphics.Add(graphic);
    }
}

By default, Geoprocessing tasks check the job status of asynchronous operations every five seconds. If you wish to change this, set the UpdateDelay property. This property is specified in milliseconds. The statement shown here sets the interval to ten seconds:

geoprocessorTask.UpdateDelay = 10000;

If you do not want the Geoprocessing task to check the status of asynchronous operations automatically, you can use the CancelJobStatusUpdates method to disable the default behavior and then check the status with the CheckJobStatusAsync method. The StatusUpdated event is used to get the job ID and call CancelJobStatusUpdates and to handle the result of the call to CheckJobStatusAsync. This approach is shown below:

// Wire status updated event and initiate the asynchronous GP operation
geoprocessorTask.StatusUpdated += geoprocessorTask_StatusUpdated;
geoprocessorTask.SubmitJobAsync(parameters);

// Manually check on the job's status. The result is passed to the StatusUpdated handler.
geoprocessorTask.CheckJobStatusAsync(jobID);
void geoprocessorTask_StatusUpdated(object sender, JobInfoEventArgs e)
{
    Geoprocessor geoprocessorTask = sender as Geoprocessor;
    switch (e.JobInfo.JobStatus)
    {
        case esriJobStatus.esriJobSubmitted:            
            // Disable automatic status checking
            geoprocessorTask.CancelJobStatusUpdates(e.JobInfo.JobId);
            break;
        case esriJobStatus.esriJobSucceeded:
            // Get results
            geoprocessorTask.GetResultDataAsync(e.JobInfo.JobId, "outerg_shp");
            break;
        case esriJobStatus.esriJobFailed:
        case esriJobStatus.esriJobTimedOut:
            MessageBox.Show("operation failed");
            break;
        }
}


12/1/2010