Recursion and QueuedTask.Run - help!!

734
7
11-13-2022 05:14 AM
Vidar
by
Occasional Contributor II

Hi,

I'm trying to go through each layer in the TOC and do get the alias name of the layer then do something that name. In order to this - I have a recursive method that loops - however you need to await QueuedTask.Run() the call to get information about an alias in layer - and in a recursive function something weird is happening - as this only gets called once and never breaks into that Queued Task code block again.

 

Something is happening here thats a bit beyond me when it gets to asynchronous programming - can anyone help me find a way to get this recursive function to work properly?

 

 

//calling code:
var map = MapView.Active.Map;
foreach (var item in map.Layers)
{
    await RecurseTocLayers(item);
}



private async Task RecurseTocLayers(Layer layer)
        {
            if (layer is BasicFeatureLayer)
            {
                FeatureLayer featureLayer = layer as FeatureLayer;

                //THIS ONLY GETS CALLED ONCE - THEN NEVER AGAIN!
                await QueuedTask.Run(() =>
                {
                    var table = featureLayer.GetTable();
                    TableDefinition tableDefinition = table.GetDefinition();
                    string alias = tableDefinition.GetAliasName();
                    //do something here with alias name.....e.g.
                    System.Diagnostics.Debug.WriteLine($"The alias name is: {alias}");
                });
            }


            if (layer is GroupLayer)
            {
                //do something here with GroupLayer, then....

                GroupLayer groupLayer = (GroupLayer)layer;
                foreach (var child in groupLayer.Layers)
                {
                    await RecurseTocLayers(child);
                }
            }
        }

 

 

ASDFDSAF

Tags (1)
0 Kudos
7 Replies
GKmieliauskas
Esri Regular Contributor

Hi,

Code you pasted has a different count of opening and closing brackets, but it works fine. Could you please share code you read layers list from TOC?

0 Kudos
Vidar
by
Occasional Contributor II

Updated - not really anything special to call code.

0 Kudos
GKmieliauskas
Esri Regular Contributor

Code below works:

 

    internal class Button1 : Button
    {
        protected async override void OnClick()
        {
            var layers = MapView.Active.Map.GetLayersAsFlattenedList();

            foreach(var layer in layers) {
                await RecurseTocLayers(layer);
            }
        }

        private async Task RecurseTocLayers(Layer layer)
        {
            if (layer is BasicFeatureLayer)
            {
                FeatureLayer featureLayer = layer as FeatureLayer;

                //THIS ONLY GETS CALLED ONCE - THEN NEVER AGAIN!
                await QueuedTask.Run(() =>
                {
                    var table = featureLayer.GetTable();
                    TableDefinition tableDefinition = table.GetDefinition();
                    string alias = tableDefinition.GetAliasName();
                    //do something here with alias name.....e.g.
                    System.Diagnostics.Debug.WriteLine($"The alias name is: {alias}");
                });
            }

	        if (layer is GroupLayer)
	        {
		        //do something here with GroupLayer, then....
		
		        GroupLayer groupLayer = (GroupLayer)layer;
		        foreach (var child in groupLayer.Layers)
		        {
			        await RecurseTocLayers(child);
                }
            }
        }
    }

 

0 Kudos
Vidar
by
Occasional Contributor II

You're right it does work. I have simplified what I have done - so I guess I'll take it from there and build it up in complexity and see what is causing the problem.

0 Kudos
GKmieliauskas
Esri Regular Contributor

Does my code work on your environment?

0 Kudos
Vidar
by
Occasional Contributor II

It does actually. However the code I left out was a line that created a row in a database (a method that is not async) based on findings earlier on i.e. the alias name. I think this may be the bit of code that is causing the code to not run properly.

0 Kudos
Wolf
by Esri Regular Contributor
Esri Regular Contributor

You should surround your code with try {} catch {} to see what errors you get.   I can see at least one bug in this snippet:

 

if (layer is BasicFeatureLayer)
            {
                FeatureLayer featureLayer = layer as FeatureLayer;

                //THIS ONLY GETS CALLED ONCE - THEN NEVER AGAIN!
                await QueuedTask.Run(() =>
                {
                    var table = featureLayer.GetTable();
                    TableDefinition tableDefinition = table.GetDefinition();
                    string alias = tableDefinition.GetAliasName();
                    //do something here with alias name.....e.g.
                    System.Diagnostics.Debug.WriteLine($"The alias name is: {alias}");
                });
            }

 

The problem is that AnnotationLayer, DimensionLayer and FeatureLayer all derive from BasicFeatureLayer.  So in your code you check if layer is of the type 'BasicFeatureLayer' and if true you assign the casted layer to the featureLayer variable:

var featureLayer = layer as FeatureLayer;

Needless to say, your featureLayer variable will be null for Dimension or Annotation layers.  Consequently, your code is using featureLayer without checking for null which will throw an exception.

The code snippet will work for maps with no Dimension or Annotation layers.