Run a geoprocessing task

Classes in the Esri.ArcGISRuntime.Tasks.Geoprocessing namespace allow you to execute tasks from a geoprocessing service in your ArcGIS Runtime app. You can work with services hosted by ArcGIS Server (online) and the ArcGIS Runtime local server (offline).

Task execution types

When working with geoprocessing services, you must be aware of the execution type that the service was published with. This execution type can be found on the service's REST page. There are three execution types that geoprocessing tasks can run on a server:

  • Execute (esriExecutionTypeSynchronous defined in task page)

    Synchronous execution is designed for fast running tasks where the client sends the request and waits for the response. This means these types of services use less resources on the server. Execute tasks on these services by calling the ExecuteAsync method of the Geoprocessor object.

  • Submit job (esriExecutionTypeAsynchronous defined in task page)

    Asynchronous services are best suited for long running jobs. For asynchronous tasks, the server returns a job ID that the client uses to poll for the task status. When the job is completed, the results can be requested from the server using the job ID. Submit an asynchronous job by calling the SubmitJobAsync method to work with the asynchronous tasks provided by these services.

  • Submit job with map server result (esriExecutionTypeAsynchronous with a map server)

    Geoprocessing services can be published with the result map service option enabled. The geoprocessing server (GPServer) creates an accompanying dynamic map server of the same name that visually represents each geodataset output parameter as a layer. This resulting dynamic map service or its service layers can then be added to your ArcGIS Runtime app as a dynamic map service. The map service's symbology is based on the symbology of the output layer that resulted from running the geoprocessing tool in ArcGIS for Desktop during the publishing process. See Defining output symbology for geoprocessing tasks for additional information on setting the symbology for a result map service.

Execute a geoprocessing task

To execute a geoprocessing task, the client must construct a request URL with the execute task URL and append name-value pairs of all the required input parameters. The name is the name of the task's input parameter, and the value is the ASCII representation of the JSON value. The input parameter names and types can be found on the service's REST page. To construct this request URL, you can use the client API. The following example shows how to construct a new Geoprocessor object, prepare a geoprocessing feature record set, add the record set to a list of geoprocessing parameters, and execute the geoprocessing task:

var serviceURL = 
var taskName = "CreateDriveTimePolygons";

// create Geoprocessor
var gp = new Geoprocessor(new Uri(serviceURL + "/" + taskName));

// set up the parameters - see serviceURL for parameter info
var parameter = new GPInputParameter();

// create a GPParameter for the input location (required input param)
var inputLocationParam = new GPFeatureRecordSetLayer("Input_Location", inputMapPoint);

// create a GPParameter for the drive times (optional input param)
var inputDriveTimesParam = new GPString("Drive_Times", "1 2 3"); // one, two, and three minute drive times

// add GPParameters to the parameter collection

// execute task with the parameter collection defined above, await the result
var result = await gp.ExecuteAsync(parameter);

The ExecuteAsync method asynchronously executes a geoprocessing task that has been defined with a synchronous execution type (on the server). Asynchronous geoprocessing tasks are executed by calling SubmitJobAsync, which is described in the Submit a job to a geoprocessing task section of this topic.

Handle task results

At the end of execution, if the task succeeds, the server will construct a response with the values of the output parameter or parameters. If the task fails, the server will generate an error response, which is returned via System.Threading.Tasks.Task.Exception. Regardless of how a task completes, a list of messages are returned that describe execution of the task.

The response (GPExecuteResult) will include the following:

  • The output parameter values—The OutParameters property of GPExecuteResult provides a read-only list of output parameters (GPParameter objects). Output parameters can be cast to the appropriate type to access their data.

    Parameter information (name and type, for example) can be found by consulting the service's REST page.

  • Execution messages—The Messages property of GPExecuteResult returns a read-only list of messages that were generated as the server executed the task (GPMessage objects).

Continuing the Drive time polygons example above, the following code locates a GPFeatureRecordSetLayer in the returned list of output GPParameter objects and adds the result features as graphics in the map:

if (result != null)
    // loop thru all output parameters
    foreach (var p in result.OutParameters)
        // find the output drive time polygons by type (GPFeatureRecordSetLayer)
        if (p.GetType() == typeof(GPFeatureRecordSetLayer))
            // (could also find it by name, which is documented in the REST page for the service)
            //  if (p.Name == "Output_Drive_Time_Polygons") { 

            // cast to GPFeatureRecordSetLayer 
            var gpFeatureLayer = p as GPFeatureRecordSetLayer;
            // get the polygon features
            var features = gpFeatureLayer.FeatureSet.Features;

            // add them to the graphics overlay
            _resultsOverlay.Graphics.AddRange(features.Select((feature, index) => new Graphic(feature.Geometry,_bufferSymbols[index])));

Submit a job to a geoprocessing task

The following image sums up the server/client communication of a submit job operation. Notice the periodic status requests sent by the client to determine the status of the job. When the server has successfully completed the execution of the job, it creates the results and inputs resources that can be accessed through the URL.

SubmitJobAsync operation: server/client communication

The following code creates a Geoprocessor task for extracting data from layers on the server. Because the underlying service has been created to use asynchronous execution, it will be called using SubmitJobAsync.

var serviceURL = 
var taskName = "Extract Data Task";
var geoprocessor = new Geoprocessor(serviceURL + "\" + taskName);

Submit a job and check status

A geoprocessing job can be submitted for asynchronous execution on the server by calling the SubmitJobAsync method. The method returns a GPJobInfo object that can be used to check that status of the job.

The GPJobInfo enumeration provides values that describe a job's status, as described in the following table:

GPJobStatus valuesDescription


The job is new.


The server has accepted the job request, and input parameters have been validated.


The job is waiting to start (server is busy with other requests).


The server is executing the job.


The server has successfully completed the job, and the output results are available.


The job has failed to execute because of invalid parameters or other geoprocessing tool failures.


Job execution has exceeded the time out threshold defined for the service.


The server is cancelling the execution of the job based on the client's request.


The request to run the job was cancelled by the client, and the server terminated the job execution.


The job is being deleted.


The job has been deleted.

The following example submits a job to extract data for a specified area. It then polls the server every two seconds with the job ID to check the status of the job.

// submit geoprocessing job
var result = await geoprocessor.SubmitJobAsync(parameter);

// keep checking the job as long as the status indicates it's still running
while (result.JobStatus != GPJobStatus.Cancelled && result.JobStatus != GPJobStatus.Deleted
    && result.JobStatus != GPJobStatus.Succeeded && result.JobStatus != GPJobStatus.TimedOut)
    // pass the unique job id to the server to check the job
    result = await geoprocessor.CheckJobStatusAsync(result.JobID);

    // wait 2 seconds before checking again
    await Task.Delay(2000);

// job is complete ...

Handle job completion

A geoprocessing job can complete under several circumstances. It can complete successfully or due to an error on the server, a time out, or because it was cancelled by the user. When a job completes, you will generally handle a successful result by reading information from the output parameters or parameters. The GetResultDataAsync method on Geoprocessor can be used to return results from the server.

Unsuccessful jobs might be handled by displaying messages that were returned from the server during job execution. GPJobInfo provides a list of messages (GPMessage objects) that were generated on the server as the job executes. GPMessage exposes a MessageType property (GPMessageType.Informative, GPMessageType.Warning, GPMessageType.Error, GPMessageType.Abort, or GPMessageType.Empty) and a Description that contains the message text. The types of messages returned by the server depends on the message level of the geoprocessing service.


If a geoprocessing service message level is set to "none", the server will not return messages.

The following example handles a successful completion by prompting the user to download and save the resulting data archive. For an unsuccessful completion, server messages are displayed in a text block in the app.

// if the job succeeded, allow the user to download the data and save it locally
if (result.JobStatus == GPJobStatus.Succeeded)
    StatusTextBlock.Text = "Finished processing. Retrieving results...";

    // get the output parameter (representing the output data file stored on the server)
    var outParam = await geoprocessor.GetResultDataAsync(result.JobID, "Output_Zip_File") as GPDataFile;
    // if the output is valid, download the data
    if (outParam != null && outParam.Uri != null)
        var webClient = new WebClient();
        var streamData = await webClient.OpenReadTaskAsync(outParam.Uri);

        // get an output file location from the user
        var dialog = new SaveFileDialog();
        dialog.FileName = "";
        dialog.Filter = "Zip file (*.zip)|*.zip";

        if (dialog.ShowDialog() == true)
            // save output data to selected local file
            using (Stream file = (Stream)dialog.OpenFile())
}else{ // job was not successful
    var messageText = string.Empty;

    // loop thru all messages that were generated during execution
    foreach (var msg in result.Messages)
        // concatenate the message descriptions
        messageText += msg.Description + "\n";

    // show the messages (last of which may be an error, time out, or cancellation)
    txtStatus.Text = messageText;

Submit a job to a geoprocessing task with map server results

If the geoprocessing service has been published with a map service enabled, the server creates a result map service that you can work with after successful task execution. Layers in the result map service can be accessed using the GetResultMapServiceLayer method on the Geoprocessor, or by building a URL in the correct format. Layers are drawn using the symbology defined in ArcMap at the time of publishing.

The following example uses GetResultMapServiceLayer, passing the job ID of a successful task:

ArcGISDynamicMapServiceLayer dynLayer = geoprocessor.GetResultMapServiceLayer(result.JobID);

You can also build a URL in the format http://<catalog-url>/<ServiceName>/MapServer/jobs/<jobid> as shown in the following example:

// start with the geoprocessing service URL, replace "GPServer" with "MapServer"
var resultUrl = geoprocessor.ServiceUri.AbsoluteUri.Replace("GPServer", "MapServer");

// add "jobs" and the successful job ID to the URL
resultUrl = resultUrl + "/jobs/" + result.JobID;

// create a new ArcGISDynamicMapServiceLayer with the result URL and add it to the map
var dynLayer = new ArcGISDynamicMapServiceLayer(new Uri(resultUrl));

If a job has failed, the server will not create result resources such as a result map service.

Consume a geoprocessing package with the local server

Working with local geoprocessing services is very similar to working with online geoprocessing service tasks. The difference is that the service is not currently running and you need to start the service. Unlike online geoprocessing service tasks, where all the service parameters are predefined by the service publisher, you must specify some of the parameters yourself based on how you want to interact with the service. These parameters include the execution type (execute, submit job, or submit job with map server result) and the maximum number of records that the service can return. Once the service is running, it is not possible to change the execution type.

Start a local geoprocessing service

Local geoprocessing services are started by creating a LocalGeoprocessingService instance using the path to the local geoprocessing package, then starting the service with the desired execution type (Execute, SubmitJob, or SubmitJobWithMapServerResult). When the service is started, a URL to the geoprocessing service can be obtained from the LocalGeoprocessingService instance.

In the following example, a local geoprocessing service is started using a geoprocessing package called contour.gpk. The execution type is SubmitJobWithMapServerResult, which means you must use the SubmitJobAsync method of the Geoprocessor class. After starting the service, its URL is stored in a variable so it can be accessed later.

private string gpkPath = @"..\samples-data\geoprocessing\contour\contour.gpk";
private string gpUrl = string.Empty;

private async void StartLocalGpService()
    var gpService = new LocalGeoprocessingService(gpkPath, GeoprocessingServiceType.SubmitJobWithMapServerResult);
    await gpService.StartAsync();
    gpUrl =  gpService.UrlGeoprocessingService;

Just as with online services, a local service URL can also be placed in a browser to explore the geoprocessing service parameters. You can use the HTML service definition and task pages at this URL to discover how to code against the service.

Once the geoprocessing service is started, programming against the service is the same as programming against an online service. You must create the geoprocessing object, and pass in the URL to the geoprocessing service plus the name of the geoprocessing task. The following code shows how to create a new Geoprocessor using a service URL that points to a specific task:

var geoprocessor = new Geoprocessor(new Uri(gpUrl + "/Contour"));

Maximum number of records

By default, the maximum number of records a local geoprocessing service will return is 1000. If the service exceeds this number, no records will be returned. The reason for this is to protect the server from large requests that could take a long time to process. If 0 results are returned but the job completes successfully, it is recommended that you always check the result and job messages to determine whether the maximum records limit was reached. This value is specified when creating the local geoprocessing service and cannot be changed once the local service is running.

Execution types in detail

In the API, execution types of a local geoprocessing service are exactly the same as those of an ArcGIS Server service. Those execution types and information on the processes running on the client machine are as follows:

  • GeoprocessingServiceType.Execute (esriExecutionTypeSynchronous)

    Starting a local geoprocessing service with the execution type set to Execute will result in a single local server process and is designed for working with quick executing geoprocessing tasks. This geoprocessing service type will not provide any feedback on the execution of the task. It will execute and return either a success or failure when the task has finished. Just as with the online geoprocessing service, you must use the ExecuteAsync method on the Geoprocessor class to work with local geoprocessing services that have been started with the Execute type.

  • GeoprocessingServiceType.SubmitJob (esriExecutionTypeAsynchronous)

    The SubmitJob mode will start two local server processes: one to do the processing and the other to monitor the processing. This allows the monitoring process to be polled by the app to get back execution messages and the status of the task. Additionally, the task can be cancelled if necessary. Once the task completes, the data can be requested from the service. Just as with the online geoprocessing service, you must use the SubmitJobAsync method.

  • GeoprocessingServiceType.SubmitJobWithMapServerResult (esriExecutionTypeAsynchronous with a map server)

    The third type of execution is treated in the same way as the SubmitJob type except that an additional local server process is started, which is used to host the result of the geoprocessing task in a local map service. This is particularly useful if your task outputs a large number of features that the client application has to symbolize and draw or if your task outputs a data type that is not supported for adding directly to the map control via the API, such as raster data. The default symbology of this map service is determined when the geoprocessing package is shared in ArcMap.

Related topics