Click or drag to resize

LocalGeoprocessingService Class

A class representing a local geoprocessing service hosted by the runtime local server.
Inheritance Hierarchy
SystemObject
  Esri.ArcGISRuntime.LocalServicesLocalService
    Esri.ArcGISRuntime.LocalServicesLocalGeoprocessingService

Namespace:  Esri.ArcGISRuntime.LocalServices
Assembly:  Esri.ArcGISRuntime.LocalServices (in Esri.ArcGISRuntime.LocalServices.dll) Version: 100.7.0.0
Syntax
public sealed class LocalGeoprocessingService : LocalService

The LocalGeoprocessingService type exposes the following members.

Constructors
  NameDescription
Public methodCode exampleLocalGeoprocessingService(String)
Initializes a new instance of the LocalGeoprocessingService class based on the provided path to a geoprocessing package.
Public methodCode exampleLocalGeoprocessingService(String, GeoprocessingServiceType)
Initializes a new instance of the LocalGeoprocessingService class based on the provided path to a geoprocessing package and service type.
Top
Properties
  NameDescription
Public propertyError
Gets the associated error if the server's Status is FailedToLoad.
(Inherited from LocalService.)
Public propertyMaxRecords
Gets or sets the maximum number of records that can be returned by the Geoprocessing service.
Public propertyCode exampleName
Gets the unique auto-assigned name for the service.
(Inherited from LocalService.)
Public propertyPackagePath
Gets the path of the package file on which the LocalService is based.
(Inherited from LocalService.)
Public propertyServiceType
Gets or sets the execution type of the local geoprocessing service.
Public propertyCode exampleStatus
Gets the local server status.
(Inherited from LocalService.)
Public propertyUrl
Gets the Url of the local geoprocessing service.
(Overrides LocalServiceUrl.)
Top
Methods
  NameDescription
Public methodStartAsync
Asynchronously starts the local geoprocessing service.
(Overrides LocalServiceStartAsync.)
Public methodCode exampleStopAsync
Asynchronously stops this local service instance, and returns a Task object.
(Inherited from LocalService.)
Top
Events
  NameDescription
Public eventCode exampleStatusChanged
Occurs when Status of this local service has changed.
(Inherited from LocalService.)
Top
Remarks

A single local geoprocessing service instance corresponds directly to a geoprocessing package shared from ArcGIS for Desktop. One or more geoprocessing tasks may be exposed by the local geoprocessing service depending on the number of individual tool or script results contained within the geoprocessing package. When starting local geoprocessing services there are a number of properties you must choose values for which are usually determined by the server administrator for online geoprocessing services hosted by ArcGIS for Server.

These properties are: Service execution type: The ServiceType property determines whether the service will run the task asynchronously or synchronously. This affects how the client application you are developing interacts with the runtime local server and gets the result from the task. When a service is set to SynchronousExecute (synchronous) operation, the client waits for the task to finish. Typically, a service that will run tasks synchronously should execute quickly (five seconds or less). A service should be set to use the AsynchronousSubmit (asynchronous) if one or more of that tasks within that service will takes longer to run. When using the SubmitJob mode the client application must periodically ask the server if the task has finished and, if it has finished, get the result. The GeoprocessingServiceType enumeration values which determine the synchronous or asynchronous service operation are called "Execute" and "SubmitJob" to align them with the corresponding methods on the Geoprocessor task API and to differentiate them from the synchronous or asynchronous usage. You must use the method which corresponds to the GeoprocessingServiceType of the local geoprocessing service you are working with. The service mode AsynchronousSubmitWithMapServiceResult will enable you to display the results of the task within a local map service. Maximum number of records returned: The maximum number of results the service can return to a client. Setting this value to a large number means your runtime local server can handle sending a lot of individual records or features to the client application. Whether you choose this pattern depends on the number and complexity of the feature geometries. If you do not want to return any features, set this value to 0 (zero). Typically, you set this value to zero only when you create the service as AsynchronousSubmitWithMapServiceResult. To determine whether the MaxRecords limits has been exceeded you should check the exceeded transfer limit property of the feature set or record set returned by the task. The exceeded transfer limit property will be set to true when the number of records and features of the output parameter exceed the maximum number of records specified by the service. this information is also included in the Messages of GeoprocessingJob returned by the service.

Once you have created a new LocalGeoprocessingService and specified the PackagePath, ServiceType and MaxRecords properties, starting the service via the StartAsync method will populate the Url property. It is this last property, the URL of the local geoprocessing service that you provide a GeoprocessingTask task with in order to interact with the tasks exposed by the service. Additionally you can use the static GetServiceAsyncTask method to instantiate and start a new local geoprocessing service.

Examples

WPF

Example Name: LocalServerGeoprocessing

Create contour lines from local raster data using a local geoprocessing package `.gpk` and the contour geoprocessing tool.

Code example screen shot.

C#
// Copyright 2018 Esri.
// 
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
// You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
// language governing permissions and limitations under the License.

using ArcGISRuntime.Samples.Managers;
using Esri.ArcGISRuntime.LocalServices;
using Esri.ArcGISRuntime.Mapping;
using Esri.ArcGISRuntime.Tasks;
using Esri.ArcGISRuntime.Tasks.Geoprocessing;
using System;
using System.IO;
using System.Windows;
using System.Windows.Controls;

namespace ArcGISRuntime.WPF.Samples.LocalServerGeoprocessing
{
    [ArcGISRuntime.Samples.Shared.Attributes.Sample(
        "Local Server geoprocessing",
        "Local Server",
        "This sample demonstrates how to perform geoprocessing tasks using Local Server.",
        "This sample depends on the local server being installed and configured. See https://developers.arcgis.com/net/latest/wpf/guide/local-server.htm for details and instructions.\nSample data is loaded in the background.\nNote that the functionality used by this sample requires that Geoprocessing packages be enabled in the ArcGISLocalServer.AGSDeployment file that is included in your project. See [Create a Local Server deployment](https://developers.arcgis.com/net/latest/wpf/guide/create-a-local-server-deployment.htm) for more information.")]
    [ArcGISRuntime.Samples.Shared.Attributes.OfflineData("f7c7b4a30fb9415896ba0d1921fe014b", "da9e565a52ca41c1937cff1a01017068")]
    public partial class LocalServerGeoprocessing
    {
        // Hold a reference to the local geoprocessing service
        private LocalGeoprocessingService _gpService;

        // Hold a reference to the task
        private GeoprocessingTask _gpTask;

        // Hold a reference to the job
        private GeoprocessingJob _gpJob;

        public LocalServerGeoprocessing()
        {
            InitializeComponent();

            // set up the sample
            Initialize();
        }

        private async void Initialize()
        {
            // Create a map and add it to the view
            MyMapView.Map = new Map(Basemap.CreateLightGrayCanvasVector());

            // Load the tiled layer and get the path
            string rasterPath = GetRasterPath();

            // Create a tile cache using the path to the raster
            TileCache myTileCache = new TileCache(rasterPath);

            // Create the tiled layer from the tile cache
            ArcGISTiledLayer tiledLayer = new ArcGISTiledLayer(myTileCache);

            // Try to load the tiled layer
            try
            {
                // Wait for the layer to load
                await tiledLayer.LoadAsync();

                // Zoom to extent of the tiled layer
                await MyMapView.SetViewpointGeometryAsync(tiledLayer.FullExtent);
            }
            catch (Exception)
            {
                MessageBox.Show("Couldn't load the tile package, ending sample load.");
                return;
            }

            // Add the layer to the map
            MyMapView.Map.OperationalLayers.Add(tiledLayer);

            // Try to start Local Server
            try
            {
                // LocalServer must not be running when setting the data path.
                if (LocalServer.Instance.Status == LocalServerStatus.Started)
                {
                    await LocalServer.Instance.StopAsync();
                }

                // Set the local data path - must be done before starting. On most systems, this will be C:\EsriSamples\AppData.
                // This path should be kept short to avoid Windows path length limitations.
                string tempDataPathRoot = Directory.GetParent(Environment.GetFolderPath(Environment.SpecialFolder.Windows)).FullName;
                string tempDataPath = Path.Combine(tempDataPathRoot, "EsriSamples", "AppData");
                Directory.CreateDirectory(tempDataPath); // CreateDirectory won't overwrite if it already exists.
                LocalServer.Instance.AppDataPath = tempDataPath;

                // Start the local server instance
                await LocalServer.Instance.StartAsync();
            }
            catch (Exception ex)
            {
                MessageBox.Show(String.Format("Please ensure that local server is installed prior to using the sample. See instructions in readme.md. Message: {0}", ex.Message), "Local Server failed to start");
                return;
            }

            // Get the path to the geoprocessing task
            string gpServiceUrl = GetGpPath();

            // Create the geoprocessing service
            _gpService = new LocalGeoprocessingService(gpServiceUrl, GeoprocessingServiceType.AsynchronousSubmitWithMapServiceResult);

            // Take action once the service loads
            _gpService.StatusChanged += GpServiceOnStatusChanged;

            // Try to start the service
            try
            {
                // Start the service
                await _gpService.StartAsync();
            }
            catch (Exception)
            {
                MessageBox.Show("geoprocessing service failed to start.");
            }
        }

        private async void GpServiceOnStatusChanged(object sender, StatusChangedEventArgs statusChangedEventArgs)
        {
            // Return if the server hasn't started
            if (statusChangedEventArgs.Status != LocalServerStatus.Started) return;

            // Create the geoprocessing task from the service
            _gpTask = await GeoprocessingTask.CreateAsync(new Uri(_gpService.Url + "/Contour"));

            // Update UI
            MyUpdateContourButton.IsEnabled = true;
            MyLoadingIndicator.Visibility = Visibility.Collapsed;
        }

        private void GenerateContours()
        {
            // Show the progress bar
            MyLoadingIndicator.Visibility = Visibility.Visible;
            MyLoadingIndicator.IsIndeterminate = false;

            // Create the geoprocessing parameters
            GeoprocessingParameters gpParams = new GeoprocessingParameters(GeoprocessingExecutionType.AsynchronousSubmit);

            // Add the interval parameter to the geoprocessing parameters
            gpParams.Inputs["ContourInterval"] = new GeoprocessingDouble(MyContourSlider.Value);

            // Create the job
            _gpJob = _gpTask.CreateJob(gpParams);

            // Update the UI when job progress changes
            _gpJob.ProgressChanged += (sender, args) =>
             {
                 Dispatcher.Invoke(() => { MyLoadingIndicator.Value = _gpJob.Progress; });
             };

            // Be notified when the task completes (or other change happens)
            _gpJob.JobChanged += GpJobOnJobChanged;

            // Start the job
            _gpJob.Start();
        }

        private async void GpJobOnJobChanged(object o, EventArgs eventArgs)
        {
            // Show message if job failed
            if (_gpJob.Status == JobStatus.Failed)
            {
                MessageBox.Show("Job Failed");
                return;
            }

            // Return if not succeeded
            if (_gpJob.Status != JobStatus.Succeeded) { return; }

            // Get the URL to the map service
            string gpServiceResultUrl = _gpService.Url.ToString();

            // Get the URL segment for the specific job results
            string jobSegment = "MapServer/jobs/" + _gpJob.ServerJobId;

            // Update the URL to point to the specific job from the service
            gpServiceResultUrl = gpServiceResultUrl.Replace("GPServer", jobSegment);

            // Create a map image layer to show the results
            ArcGISMapImageLayer myMapImageLayer = new ArcGISMapImageLayer(new Uri(gpServiceResultUrl));

            // Load the layer
            await myMapImageLayer.LoadAsync();

            // This is needed because the event comes from outside of the UI thread
            Dispatcher.Invoke(() =>
            {
                // Add the layer to the map
                MyMapView.Map.OperationalLayers.Add(myMapImageLayer);

                // Hide the progress bar
                MyLoadingIndicator.Visibility = Visibility.Collapsed;

                // Disable the generate button
                MyUpdateContourButton.IsEnabled = false;

                // Enable the reset button
                MyResetButton.IsEnabled = true;
            });
        }

        private static string GetRasterPath()
        {
            return DataManager.GetDataFolder("f7c7b4a30fb9415896ba0d1921fe014b", "RasterHillshade.tpk");
        }

        private static string GetGpPath()
        {
            return DataManager.GetDataFolder("da9e565a52ca41c1937cff1a01017068", "Contour.gpk");
        }

        private void MyResetButton_OnClick(object sender, RoutedEventArgs e)
        {
            // Remove the contour
            MyMapView.Map.OperationalLayers.RemoveAt(1);

            // Enable the generate button
            MyUpdateContourButton.IsEnabled = true;

            // Disable the reset button
            MyResetButton.IsEnabled = false;
        }

        private void MyUpdateContourButton_OnClick(object sender, RoutedEventArgs e)
        {
            // Disable the generate button
            ((Button)sender).IsEnabled = false;

            // Generate the contours
            GenerateContours();
        }
    }
}
XAML
<UserControl x:Class="ArcGISRuntime.WPF.Samples.LocalServerGeoprocessing.LocalServerGeoprocessing"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:esri="http://schemas.esri.com/arcgis/runtime/2013">
    <Grid>
        <esri:MapView x:Name="MyMapView" />
        <Border Style="{StaticResource BorderStyle}">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="auto" />
                    <RowDefinition Height="auto" />
                    <RowDefinition Height="auto" />
                    <RowDefinition Height="auto" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="2*" />
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <TextBlock
                    Text="Use the slider to select a contour interval (height difference between contour lines). Use the buttons to update or clear the contours."
                    Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3"
                    FontWeight="SemiBold" TextWrapping="Wrap" />
                <ProgressBar x:Name="MyLoadingIndicator"
                             Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3"
                             Height="15" Margin="0,5,0,0"
                             IsIndeterminate="True" />
                <Slider x:Name="MyContourSlider"
                        Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2"
                        VerticalAlignment="Center" Margin="0,5,0,0"
                        Minimum="50" Maximum="350" />
                <TextBlock x:Name="MyContourDepthLabel"
                           Grid.Row="2" Grid.Column="2"
                           VerticalAlignment="Center" Margin="0,5,0,0"
                           TextAlignment="Center"
                           Text="{Binding Value, ElementName=MyContourSlider, StringFormat=N2}" />
                <Button x:Name="MyUpdateContourButton"
                        Grid.Row="3" Grid.Column="0"
                        Content="Generate"
                        Margin="0,5,5,0"
                        IsEnabled="False"
                        Click="MyUpdateContourButton_OnClick" />
                <Button x:Name="MyResetButton"
                        Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="2"
                        Content="Reset"
                        Margin="5,5,0,0"
                        IsEnabled="False"
                        Click="MyResetButton_OnClick" />
            </Grid>
        </Border>
    </Grid>
</UserControl>
See Also
Additional Examples
Hyperlink to ExampleDescription
LocalServerGeoprocessingCreate contour lines from local raster data using a local geoprocessing package `.gpk` and the contour geoprocessing tool.
LocalServerServicesDemonstrates how to start and stop the Local Server and start and stop a local map, feature, and geoprocessing service running on the Local Server.