Select to view content in your preferred language

Simple Geoprocessing tool never finished

792
4
01-10-2024 07:53 AM
Annemiek
Occasional Contributor

Hi, after years from programming with arcobject, I am just starting to work with ArcGIS pro SDK.

I am working on an Addin for ArcGIS pro. One of the steps is to extract the rasterdata that is inside a polygon feature to a new raster. When I debug my code, I can wait for ages and will not get any result.

When I execute the same geoprocessing event by hand, it is finished in less than a second. What am I doing wrong?

My code is in the attached image. The featurelayer has a DefinitionQuery with 1polygonfeature.

 

Kind regards ,

Annemiek 

0 Kudos
4 Replies
GKmieliauskas
Esri Regular Contributor

Hi,

Could you please add the code as text ("..." on toolbar and "</>" on extended toolbar)? 

It would be easier to correct your code.

0 Kudos
Annemiek
Occasional Contributor

Here is the code:

 

public Task<bool> ExtractByMask(RasterLayer _inputRaster, FeatureLayer _maskLayer, string _outRaster)
{

return QueuedTask.Run<bool>(() =>
{
try
{

var valueArray = Geoprocessing.MakeValueArray(_inputRaster, _maskLayer);

Geoprocessing.ExecuteToolAsync("ExtractByMask", valueArray,flags: GPExecuteToolFlags.AddOutputsToMap);
return true;
}
catch (Exception exc)
{
MessageBox.Show("Exception caught in ExtractByMask: " + exc.Message);
return false;
}
});
}

0 Kudos
GKmieliauskas
Esri Regular Contributor

@KenBujais right about "async" and "await".

As I understand you use SpatialAnalyst ExtractByMask tool. There is a small difference in parameters calling from python and c#, because ExtractByMask returns result raster. Calling ExtractByMask tool from c# you need to find right place for output raster path parameter. Spatial Analyst use few different approaches for output parameters: it could be in second place or last one. More info here

 

        public async Task<bool> ExtractByMask(RasterLayer _inputRaster, FeatureLayer _maskLayer, string _outRaster)
        {
            var valueArray = Geoprocessing.MakeValueArray(_inputRaster, _maskLayer, _outRaster);
            // or
            //var valueArray = Geoprocessing.MakeValueArray(_inputRaster, _outRaster, _maskLayer);

            var gpResult = await Geoprocessing.ExecuteToolAsync("ExtractByMask_sa", valueArray, flags: GPExecuteToolFlags.AddOutputsToMap);
            return !gpResult.IsFailed;
        }

 

I would recommend to use that overload of ExecuteToolAsync. It will get you more information about executing tool. Sample from that page:

 

System.Threading.CancellationTokenSource _cts;

string ozone_points = @"C:\data\ca_ozone.gdb\O3_Sep06_3pm";

string[] args = { ozone_points, "OZONE", "", "in_memory\\raster", "300",
                    "EMPIRICAL", "300", "5", "5000",
                    "NBRTYPE=StandardCircular RADIUS=310833.272442914 ANGLE=0 NBR_MAX=10 SECTOR_TYPE=ONE_SECTOR",
                    "PREDICTION", "0.5", "EXCEED", "", "K_BESSEL" };

string tool_path = "ga.EmpiricalBayesianKriging";

_cts = new System.Threading.CancellationTokenSource();

var result = await Geoprocessing.ExecuteToolAsync(tool_path, args, null, _cts.Token,
    (event_name, o) =>  // implement delegate and handle events
    {
        switch (event_name)
        {
            case "OnValidate": // stop execute if any warnings
                if ((o as IGPMessage[]).Any(it => it.Type == GPMessageType.Warning))
                    _cts.Cancel();
                break;

            case "OnProgressMessage":
                string msg = string.Format("{0}: {1}", new object[] { event_name, (string)o });
                System.Windows.MessageBox.Show(msg);
                _cts.Cancel();
                break;

            case "OnProgressPos":
                string msg2 = string.Format("{0}: {1} %", new object[] { event_name, (int)o });
                System.Windows.MessageBox.Show(msg2);
                _cts.Cancel();
                break;
        }
    });

var ret = result;
_cts = null;

 

OnValidate you will get info about parameters validity.

0 Kudos
KenBuja
MVP Esteemed Contributor

In my functions to run Geoprocessing tools, it's an async Task and uses await when calling the ExecuteToolAsync method.

Here's an example of one of my functions that uses the Dissolve tool.

 

public static async Task<IGPResult> DissolveFeatures(FeatureClass featureClass, string DissolveFields, string StatsFields, string OutputName, GPExecuteToolFlags flags = GPExecuteToolFlags.None)
{
  List<object> arguments = new()
  {
    featureClass,
    OutputName,
    DissolveFields,
    StatsFields
  };
  IGPResult result = await Geoprocessing.ExecuteToolAsync("management.Dissolve", Geoprocessing.MakeValueArray(arguments.ToArray()), null, null, null, flags);
  return result;
}

//this is how I use the function and the returned result
bool results = await QueuedTask.Run(async () =>
{
  //lots of code
  path = geodatabase.GetPath().AbsolutePath
  IGPResult DissolvedSummaryResult = await Utilities.DissolveFeatures(JoinFC, StrataFieldName, StatField, $"{path}\\JoinedPointDissolve", GPExecuteToolFlags.None);
  if (DissolvedSummaryResult.IsFailed)
  {
    // do something if it fails
    return false;
  }
  using FeatureClass DissolveSummaryFC = geodatabase.OpenDataset<FeatureClass>("JoinedPointDissolve");
  //lots more code
)};

 

I also notice you're not specifying the Toolbox where ExtractByMask is located in the tool path property. In my code, the tool is in the Data Management toolbox, so I call it using "management.Dissolve". If you look at the documentation for the tool you're using, in the Parameters section, you can see how it's called in Python. To use it in .NET, just remove "arcpy."

python.png

0 Kudos