How to quarantine async

3372
5
08-21-2015 05:03 AM
AdamDavis
Occasional Contributor

Hi,

Esri's usage of async looks all very well for completely new code.

However, we have a very large existing code base that runs on ArcGIS and a couple of other platforms. We are struggling to see how we can use a lot of our existing code within both the new ArcGIS Pro async model and sync platforms like ArcGIS, AutoCAD & Microstation.

Async can be a bit like a virus in a codebase - once you start putting it in you have to follow it right through the codebase. That's fine for tiny little apps but for a large existing codebase - major rework.

Any advice on how we can turn async back to sync safely without breaking ArcGIS Pro.

Thanks in advance,


Adam

0 Kudos
5 Replies
AdamDavis
Occasional Contributor

Just to add to this.

Anything that changes the UI seems to be a problem.

For example.

QueuedTask.Run(() => LayerFactory.CreateFeatureLayer(new Uri(Path.Combine(this.GeodatabasePath, this.FeatureClassName)), MapView.Active.Map));

If I am running sync then obviously this does not complete. I've tried things like GetAwaiter() and GetAwaiter().GetResult() but no luck,

The main way of getting it to work is to sync up the User Interface by showing a MessageBox

MessageBox.Show("Hello");

Then I can see the Layer in ArcGIS Pro.

I even made an auto disappearing MessageBox after x milliseconds; that works but is tedious.

Are there any functions in the SDK that I can use to force a UI refresh of some kind.

Thanks,


Adam

0 Kudos
ThomasEmge
Esri Contributor

Adam,

if you await any of the async functions, you are essentially writing sequentially executed code. The fact that the functionality of the async methods is going of to spin up new threads or does whatever it needs to do is kind of not relevant.

This line in code will not advance until the layer is generated and added to the container.

await QueuedTask.Run(() => 
{
    LayerFactory.CreateLayer(new Uri(Path.Combine(CoreModule.CurrentProject.DefaultGeodatabasePath, "Sample")), MapView.Active.Map);
});

You can choose not to await the XXAsync methods, however that choice depends on your code/workflow logic. One of the reasons for Pro is to free the UI thread from business logic and always stay responsive.

0 Kudos
AdamDavis
Occasional Contributor

Hi Thomas,

Thanks for your reply.

That was precisely my point.


If we use await in a function then that function has to be marked as async and so it goes on up the entire stack. At some point we want to sync up and also be guaranteed, for instance, that the FeatureClass we create in code (annoyingly via Geoprocessing) has been created before we make a field, before we then add a row etc etc.

That's fine for greenfield development but adding this to a large existing codebase is going to require major rework. The time (and therefore also cost) of updating the code to work with Pro will affect both when we can release a version for Pro and and indeed whether it is commercially worth it.

Given that Esri decided to go all asyncy with it latest API; does Esri have any tips on how best to manage a single codebase that functions under both ArcGIS and Pro? Perhaps a reasonably complex example that can be compiled to cover both platforms.

Thanks,

Adam

0 Kudos
CharlesMacleod
Esri Regular Contributor

Hi Adam,

This is not possible. 10.x .Net SDK APIs are 32 bit ArcObjects (AO), single threaded and (must) reference PIAs installed as part of the AO SDK. Pro is 64 bit and multi-threaded. Pro Add-ins do not use the AO PIAs and are not COM.

The closest you can come to a single codebase would be if you were developing exclusively in python on top of arcpy.

You can find an FAQ here which explains more of the new Pro API and transitioning from ArcObjects:

http://github.com/Esri/arcgis-pro-sdk/wiki/FAQ

0 Kudos
AdamDavis
Occasional Contributor

Hi Charles,

Thanks for that.

I was thinking of something a little more complex.

We have products that have similar functionality on AutoCAD, Microstation and ArcGIS. We abstract away the differences by creating an abstract CommonPlatform that binds to an AutoCADPlatform, a MicrostationPlatform, a FileGDb platform or an ArcGISPlatform depending on the underlying product.


The plan is that as we add new platforms either from new vendors or updated API's then it is a relatively simple matter of implementing the new platform calls. That's what happened when Microstation recently released a Beta of their new API. Recent AutoCAD can be used async but it's optional anyway. We are adding an ArcGISProPlatform but it's proving a bit painful due to it's async nature but I'm sure we'll get there in the end.

2 separate codebases could be created (in our case 6). Any new updates to our functionality have to be replicated on all codebases. Never been keen on that solution which is why we went with the platform idea.

We, probably like many ESRI Partners, are looking at Pro and wondering how best to refactor our codebases in the most efficient and cost effective way possible. Any tips, examples etc that help us towards tha goal will save a monumental amount of time and resources in comparison to us all reiventing the same wheel.

Thanks

Adam

0 Kudos