Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

This sample code for the Bing Maps REST Services Toolkit uses a delegate to get the response and then outputs a message from within the delegate method. However, it does not demonstrate how to access the response from outside of the invocation of GetResponse. I cannot figure out how to return a value from this delegate. In other words, let us say I want to use the value of the longitude variable right before the line Console.ReadLine(); How do I access that variable in that scope?

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using BingMapsRESTToolkit;
    using System.Configuration;
    using System.Net;
    using System.Runtime.Serialization.Json;

    namespace RESTToolkitTestConsoleApp
    {

        class Program
        {

            static private string _ApiKey = System.Configuration.ConfigurationManager.AppSettings.Get("BingMapsKey");

            static void Main(string[] args)
            {
                string query = "1 Microsoft Way, Redmond, WA";

                Uri geocodeRequest = new Uri(string.Format("http://dev.virtualearth.net/REST/v1/Locations?q={0}&key={1}", query, _ApiKey));

                GetResponse(geocodeRequest, (x) =>
                {
                    Console.WriteLine(x.ResourceSets[0].Resources.Length + " result(s) found.");
                    decimal latitude = (decimal)((Location)x.ResourceSets[0].Resources[0]).Point.Coordinates[0];
                    decimal longitude = (decimal)((Location)x.ResourceSets[0].Resources[0]).Point.Coordinates[1];
                    Console.WriteLine("Latitude: " + latitude);
                    Console.WriteLine("Longitude: " + longitude);
                });
                Console.ReadLine();
            }

            private static void GetResponse(Uri uri, Action<Response> callback)
            {
                WebClient wc = new WebClient();
                wc.OpenReadCompleted += (o, a) =>
                {
                    if (callback != null)
                    {
                        // Requires a reference to System.Runtime.Serialization
                        DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Response));
                        callback(ser.ReadObject(a.Result) as Response);
                    }
                };
                wc.OpenReadAsync(uri);
            }
        }
    }
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
369 views
Welcome To Ask or Share your Answers For Others

1 Answer

For the provided example AutoResetEvent class could be utilized to control the flow, in particular to wait asynchronous WebClient.OpenReadCompleted Event is completed like this:

class Program
{
    private static readonly string ApiKey = System.Configuration.ConfigurationManager.AppSettings.Get("BingMapsKey");
    private static readonly AutoResetEvent StopWaitHandle = new AutoResetEvent(false);

    public static void Main()
    {
        var query = "1 Microsoft Way, Redmond, WA";
        BingMapsRESTToolkit.Location result = null;

        Uri geocodeRequest = new Uri(string.Format("http://dev.virtualearth.net/REST/v1/Locations?q={0}&key={1}",
            query, ApiKey));
        GetResponse(geocodeRequest, (x) =>
        {
           if (response != null &&
              response.ResourceSets != null &&
              response.ResourceSets.Length > 0 &&
              response.ResourceSets[0].Resources != null &&
              response.ResourceSets[0].Resources.Length > 0)
           {
               result = response.ResourceSets[0].Resources[0] as BingMapsRESTToolkit.Location;
            }
        });
        StopWaitHandle.WaitOne(); //wait for callback
        Console.WriteLine(result.Point); //<-access result 
        Console.ReadLine();

    }

    private static void GetResponse(Uri uri, Action<Response> callback)
    {
        var wc = new WebClient();
        wc.OpenReadCompleted += (o, a) =>
        {
            if (callback != null)
            {
                DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Response));
                callback(ser.ReadObject(a.Result) as Response);
            }
            StopWaitHandle.Set(); //signal the wait handle
        };
        wc.OpenReadAsync(uri);
    }

}

Option 2

Or to switch to ServiceManager class that makes it easy when working via asynchronous programming model:

public static void Main()
{
    var task = ExecuteQuery("1 Microsoft Way, Redmond, WA");
    task.Wait();
    Console.WriteLine(task.Result);
    Console.ReadLine();
}

where

public static async Task<BingMapsRESTToolkit.Location> ExecuteQuery(string queryText)
{
    //Create a request.
    var request = new GeocodeRequest()
        {
            Query = queryText,
            MaxResults = 1,
            BingMapsKey = ApiKey
    };
    //Process the request by using the ServiceManager.
    var response = await request.Execute();
    if (response != null &&
            response.ResourceSets != null &&
            response.ResourceSets.Length > 0 &&
            response.ResourceSets[0].Resources != null &&
            response.ResourceSets[0].Resources.Length > 0)
    {
         return response.ResourceSets[0].Resources[0] as BingMapsRESTToolkit.Location;
    }
    return null;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...