How can I run 2 QueryFeaturesAsync in parallel ?

510
5
Jump to solution
10-02-2022 03:25 AM
MarcHillman
New Contributor III

Having just discovered ServiceFeatureTable I am now converting my code to use them. I have an opportunity to execute 2 queries in parallel, but I can't work out how to do it.

Code fragment 1 shows my Serial code. It works correctly.

 

        Dim sft_SA4 As New ServiceFeatureTable(New Uri($"{MAPSERVER_SA4}"))
        Dim sft_SA3 As New ServiceFeatureTable(New Uri($"{MAPSERVER_SA3}"))
        Dim myquery As New QueryParameters
        Dim fc1 As FeatureQueryResult, fc2 As FeatureQueryResult

        fc1 = Await sft_SA4.QueryFeaturesAsync(myquery).ConfigureAwait(False)
        fc2 = Await sft_SA3.QueryFeaturesAsync(myquery).ConfigureAwait(False)

 

Code fragment 2 shows my attempt to run both these queries in parallel. It compiles, but when run it just hangs at the WhenAll statement

Dim sft_SA4 As New ServiceFeatureTable(New Uri($"{MAPSERVER_SA4}"))
Dim sft_SA3 As New ServiceFeatureTable(New Uri($"{MAPSERVER_SA3}"))
Dim myquery As New QueryParameters
Dim fc1 As FeatureQueryResult, fc2 As FeatureQueryResult
Dim t1 = sft_SA4.QueryFeaturesAsync(myquery)
Dim t2 = sft_SA3.QueryFeaturesAsync(myquery)
Await Task.WhenAll(t1, t2)      ' both complete
fc1 = t1.Result
fc2 = t1.result

 What have I done wrong? (myquery is populated elsewhere, but left out for clarity)

0 Kudos
1 Solution

Accepted Solutions
MichaelBranscomb
Esri Frequent Contributor

Apologies. 

I just tried your code and it appear to work fine: control returns to the UI thread and the async tasks continue to run effectively in the background. For the query I'm using 1=1 which retrieves all features which appear to be about 100 per layer. Note it took almost 1min from submitting the query to the service responding so I do think the server/service appears to be running a little slowly.

 

string MAPSERVER_SA4 = "https://geo.abs.gov.au/arcgis/rest/services/ASGS2021/SA4/MapServer/0";
string MAPSERVER_SA3 = "https://geo.abs.gov.au/arcgis/rest/services/ASGS2021/SA4/MapServer/1";
ServiceFeatureTable sft_SA4 = new ServiceFeatureTable (new Uri($"{MAPSERVER_SA4}"));
ServiceFeatureTable sft_SA3 = new ServiceFeatureTable(new Uri($"{MAPSERVER_SA3}"));
QueryParameters myquery = new QueryParameters() { WhereClause="1=1"};
FeatureQueryResult fc1; FeatureQueryResult fc2;

var t1 = sft_SA4.QueryFeaturesAsync(myquery);
var t2 = sft_SA3.QueryFeaturesAsync(myquery);
await Task.WhenAll(t1, t2);    // both complete
fc1 = t1.Result;
fc2 = t1.Result;

 

View solution in original post

0 Kudos
5 Replies
MichaelBranscomb
Esri Frequent Contributor

Because you're awaiting the task, the second query will be executed after the first one completes. To execute the tasks in parallel see Task.WhenAll Method (System.Threading.Tasks) | Microsoft Learn or Parallel.ForEach Method (System.Threading.Tasks) | Microsoft Learn

While you're migrating to use the more data-oriented end points - we now recommend using Class ServiceGeodatabase rather than the more granular ServiceFeatureTable because your FeatureServer and therefore the client ServiceGeodatabase may contain behavior that operates on multiple tables in the service. 

Some background info:

 

0 Kudos
MarcHillman
New Contributor III

Thanks @MichaelBranscomb, but you seem to be only looking at the first fragment of code. I recognised it was serial. The second fragment of my code is my attempt to do these in parallel. I am using WhenAll to await completion of both. It doesn't work, and I seek guidance as to what I have done wrong.

0 Kudos
MichaelBranscomb
Esri Frequent Contributor

Apologies. 

I just tried your code and it appear to work fine: control returns to the UI thread and the async tasks continue to run effectively in the background. For the query I'm using 1=1 which retrieves all features which appear to be about 100 per layer. Note it took almost 1min from submitting the query to the service responding so I do think the server/service appears to be running a little slowly.

 

string MAPSERVER_SA4 = "https://geo.abs.gov.au/arcgis/rest/services/ASGS2021/SA4/MapServer/0";
string MAPSERVER_SA3 = "https://geo.abs.gov.au/arcgis/rest/services/ASGS2021/SA4/MapServer/1";
ServiceFeatureTable sft_SA4 = new ServiceFeatureTable (new Uri($"{MAPSERVER_SA4}"));
ServiceFeatureTable sft_SA3 = new ServiceFeatureTable(new Uri($"{MAPSERVER_SA3}"));
QueryParameters myquery = new QueryParameters() { WhereClause="1=1"};
FeatureQueryResult fc1; FeatureQueryResult fc2;

var t1 = sft_SA4.QueryFeaturesAsync(myquery);
var t2 = sft_SA3.QueryFeaturesAsync(myquery);
await Task.WhenAll(t1, t2);    // both complete
fc1 = t1.Result;
fc2 = t1.Result;

 

0 Kudos
MarcHillman
New Contributor III

Wow - 1 minute for queries in parallel ! After about 30s I bailed out assuming it had 'hung'. When I profile the serial case, I get 1003 mS. I have no idea why the parallel case takes so much longer, but I think I'll stick with the serial method.

I have just realised that myquery selects a single feature, whilst yours selects them all. Even so, my single feature query is too slow (in parallel) to be useable.

 

Dim t = Stopwatch.StartNew
fc1 = Await sft_SA4.QueryFeaturesAsync(myquery).ConfigureAwait(False)
fc2 = Await sft_SA3.QueryFeaturesAsync(myquery).ConfigureAwait(False)
t.Stop()

 

 

0 Kudos
MichaelBranscomb
Esri Frequent Contributor

You might try testing the service via the HTML pages as well, to help track down where the bottleneck is e.g. the query below uses 1=1 to get all 108 features from your service, including geometry. If you don't need the geometry you can disable that part of the query - in the API you'd specify ReturnGeometry = false.

https://geo.abs.gov.au/arcgis/rest/services/ASGS2021/SA4/MapServer/0/query?where=1=1&text=&objectIds...

 

0 Kudos