-2

I am using the arcGIS SDK in C# to search for addresses. What i would like to do is search for multiple addresses and then executing a method when all the addresses are found. This will most likely be achieved by using a loop.

Here is the code to find an address on the map:

public async void searchSubjectAddress(string sAddress)
{
    var uri = new Uri("http://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer");

    var token = string.Empty;
    var locator = new OnlineLocatorTask(uri, token);

    var info = await locator.GetInfoAsync();

    var singleAddressFieldName = info.SingleLineAddressField.FieldName;

    var address = new Dictionary<string, string>();

    address.Add(singleAddressFieldName, sAddress);

    var candidateFields = new List<string> { "Score", "Addr_type", "Match_addr", "Side" };

    var task = locator.GeocodeAsync(address, candidateFields, MyMapView.SpatialReference, new CancellationToken());

    IList<LocatorGeocodeResult> results = null;
    try
    {
        results = await task;

        if (results.Count > 0)
        {
            var firstMatch = results[0];
            var matchLocation = firstMatch.Location as MapPoint;

            Console.WriteLine($"Found point: {matchLocation.ToString()}");
            MyMapView.SetView(matchLocation);                    
        }

    }
    catch (Exception ex)
    {
        Console.WriteLine("Could not find point");
        var msg = $"Exception from geocode: {ex.Message} At address: {sAddress}";
        Console.WriteLine(msg);
    }
}

I am currently following this tutorial: https://developers.arcgis.com/net/10-2/desktop/guide/search-for-places.htm

I can find a single address, but the asynchronous tasks are a bit confusing. The code must be executed with the asynchronous tasks to function, so i cant change that.

To use this in an example: I want to get the distance between one property and several others. I only have access to the street addresses, so i use the above code to find the address and fetch the Geo-coordinates. Then i save those coordinates in a list for later use.

My problem is that when i want to execute the later methods, the async tasks are still running and my program executes the later methods regardless of whether the async methods are completed. When i change the method to a Task type instead of void, i usually end up with an endless wait with no tasks being accomplished.

I would like to know how i can loop the above method synchronously (let each new tasks only run when the older ones are finished) through a list of addresses and then run a method when all async tasks are finished. It would also be nice if the async tasks stop when a resulting address is found.

Help would be much appreciated!

sayah imad
  • 1,507
  • 3
  • 16
  • 24

1 Answers1

0

Change

public async void searchSubjectAddress(string sAddress)

to

  public async Task searchSubjectAddress(string sAddress)

Then whatever is calling searchSubjectAddress can await this call, so you know when it's complete. You might also consider making it return Task < SearchResult> instead so you can get the address sent back to the caller. Generally when you write "async void" you're setting yourself up for problems, so try to always make things "async Task" or "async Task< T>" instead.

On a side note: The v10.x releases have long been deprecated/unsupported, and you really should move to v100.8

dotMorten
  • 1,953
  • 1
  • 14
  • 10
  • Thanks for the reply. How would i run this method as a task? I cant assign the method as `Task`, because the `T` object is missing, so i cant return for instance `Task.Completed`. Also, running the method as `searchSubjectAddress().Wait()` causes the program to be stuck in an endless cycle or something, meaning that the async methods aren't stopping properly. Also the reason im using ArcGIS 10.27 is because it has access to functionality that the newer versions dont have, but if there is a tutorial to explain how to add a v100 map to an existing project, then ill switch. – Thys Wentzel Jul 31 '20 at 06:19
  • @ThysWentzel A "stuck" program means that you have a deadlock and incorrect async code. A pretty common error for inexperienced async programmers (multithreading and async are pretty tough). You should show us a [mcve] that reproduces your issue *including* your calling code. – dymanoid Jul 31 '20 at 11:53
  • Don't _ever_ use .Wait or .Result on a task, unless you're 100% sure your app is single threaded (it's not). As you found it can deadlock. < T > is a generic expression - replace with a type. You might want to read up on .NET Generics. If you're confused about Task< T > and what that means, a tutorial on how to use tasks in .NET first might be good. I'd recommend these 6 short videos as a good start: https://channel9.msdn.com/Series/Three-Essential-Tips-for-Async – dotMorten Jul 31 '20 at 17:12