I understand that each and every object in the ArcGIS.Core.Data lives on the MCT and therefore has to be used within QueuedTask.Run(..) scope. This makes ArcGIS Pro actually to kind of a single threaded application, as soon as it comes to data access.
While looking through the community samples, I stumbled across arcgis-pro-sdk-community-samples/CoreHost/CoreHostSample at master · Esri/arcgis-pro-sdk-community-s... where the Geodatabase-Object is used in the main thread (being an STA Thread), without QueuedTask.
This led me to the first question / test program: What happens, if the geodatabase object is instantiated and used in one background thread? Seems to work fine.
Second question / test program: What happens, if two geodatabase objects are created in two different (STA-) threads and some work is done on different tables? Seems to work fine.
Question is: Is this supported in any way? I do understand, that I will run into problems as soon as I try to pass objects from one thread to another. Updating data might also become critical, as there might be no synchronization context. But if I stay in a read-only context, is it ok to create "my own" geodatabase object in "my own" thread?
Kind Regards
Jens
Solved! Go to Solution.
Hi Jens, so my replies:
>>>This makes ArcGIS Pro actually to kind of a single threaded application, as soon as it comes to data access
In Pro, the threading model is simplified for developers so all you have to worry about is a simple "binary" condition: Foreground -or- Background. Pro handles the rest. Internally, Pro delegates work submitted on the QueuedTask to its own internal thread pool and makes sure that any changes are propagated to all instances of Pro's internal state on each of its threads. Which thread your code actually runs on is an internal detail controlled by QueuedTask. You submit your "job" (work defined in the lambda) to QueuedTask and QueuedTask does the rest. Specifically with regards to databases the same rules apply in Pro as with any database application - Enterprise databases are throttled by their own internal connection pools, which user credentials are used to connect and perform edits, write locks, etc.,etc. File gdb is single user access only regardless of threading behavior of the application. You can read more of Pro's internal threading behavior here:
>>>>>Question is: Is this supported in any way? I do understand, that I will run into problems as soon as I try to pass objects from one thread to another. Updating data might also become critical, as there might be no synchronization context. But if I stay in a read-only context, is it ok to create "my own" geodatabase object in "my own" thread?
Yes it is ok. The rules are simple: it must be instantiated on an STA (which QueuedTask provides) and you must ~always~ access the class on the same (STA) thread upon which it was created. Generally this means that the lifetime of your class instances should be strapped to the scope of the lambda within the QueuedTask.Run (or System thread in the case of CoreHost). So when the lambda goes out of scope all the instances (like Geodatabase, FeatureClass, etc) are disposed. Creating multiple copies of the same geodatabase across multiple STAs should work in theory for RO access (assuming underlying database resources are sufficient) but is not something we support currently.
Last, with regards to the CoreHost samples, They are running on top of the Core.Data API ~outside~ of Pro so the Framework is neither instantiated nor available. As such, the sample is using an STA from the system thread pool (because QueuedTask is ~not~ available outside of the Framework). It may come as some surprise that System Task is MTA and so is not suitable. The sample, therefore, uses a utility method to.spin off a System.Thread configured as STA yet wait on a System.Task for completion (I copied and pasted that code from stackoverflow - I think I put the url in the comments of the sample). At 1.2 we will provide a class called QueuedWorker for use in CoreHost scenarios that will have a Run method similar to QueuedTask.Run and should simplify that pattern (ie make it very similar to code you would write inside an Addin in Pro without resorting to using a System.Thread...unless you wanted to ;-).
Hi Jens, so my replies:
>>>This makes ArcGIS Pro actually to kind of a single threaded application, as soon as it comes to data access
In Pro, the threading model is simplified for developers so all you have to worry about is a simple "binary" condition: Foreground -or- Background. Pro handles the rest. Internally, Pro delegates work submitted on the QueuedTask to its own internal thread pool and makes sure that any changes are propagated to all instances of Pro's internal state on each of its threads. Which thread your code actually runs on is an internal detail controlled by QueuedTask. You submit your "job" (work defined in the lambda) to QueuedTask and QueuedTask does the rest. Specifically with regards to databases the same rules apply in Pro as with any database application - Enterprise databases are throttled by their own internal connection pools, which user credentials are used to connect and perform edits, write locks, etc.,etc. File gdb is single user access only regardless of threading behavior of the application. You can read more of Pro's internal threading behavior here:
>>>>>Question is: Is this supported in any way? I do understand, that I will run into problems as soon as I try to pass objects from one thread to another. Updating data might also become critical, as there might be no synchronization context. But if I stay in a read-only context, is it ok to create "my own" geodatabase object in "my own" thread?
Yes it is ok. The rules are simple: it must be instantiated on an STA (which QueuedTask provides) and you must ~always~ access the class on the same (STA) thread upon which it was created. Generally this means that the lifetime of your class instances should be strapped to the scope of the lambda within the QueuedTask.Run (or System thread in the case of CoreHost). So when the lambda goes out of scope all the instances (like Geodatabase, FeatureClass, etc) are disposed. Creating multiple copies of the same geodatabase across multiple STAs should work in theory for RO access (assuming underlying database resources are sufficient) but is not something we support currently.
Last, with regards to the CoreHost samples, They are running on top of the Core.Data API ~outside~ of Pro so the Framework is neither instantiated nor available. As such, the sample is using an STA from the system thread pool (because QueuedTask is ~not~ available outside of the Framework). It may come as some surprise that System Task is MTA and so is not suitable. The sample, therefore, uses a utility method to.spin off a System.Thread configured as STA yet wait on a System.Task for completion (I copied and pasted that code from stackoverflow - I think I put the url in the comments of the sample). At 1.2 we will provide a class called QueuedWorker for use in CoreHost scenarios that will have a Run method similar to QueuedTask.Run and should simplify that pattern (ie make it very similar to code you would write inside an Addin in Pro without resorting to using a System.Thread...unless you wanted to ;-).
Charles,
thanks a lot for your comprehensive answer. It is really helpful to understand those details of the Threading Model.
Regards
Jens