#c# #callback #delegates #bing-maps
#c# #обратный вызов #делегаты #bing-maps
Вопрос:
Этот пример кода для Bing Maps REST Services Toolkit использует делегат для получения ответа, а затем выводит сообщение из метода делегата. Однако в нем не демонстрируется, как получить доступ к ответу извне вызова GetResponse. Я не могу понять, как вернуть значение из этого делегата. Другими словами, допустим, я хочу использовать значение longitude
переменной прямо перед строкой Console.ReadLine();
, как мне получить доступ к этой переменной в этой области?
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}amp;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);
}
}
}
Ответ №1:
Приведенный пример AutoResetEvent class
может быть использован для управления потоком, в частности, для ожидания завершения асинхронного WebClient.OpenReadCompleted
события следующим образом:
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}amp;key={1}",
query, ApiKey));
GetResponse(geocodeRequest, (x) =>
{
if (response != null amp;amp;
response.ResourceSets != null amp;amp;
response.ResourceSets.Length > 0 amp;amp;
response.ResourceSets[0].Resources != null amp;amp;
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);
}
}
Вариант 2
Или переключиться на ServiceManager class
, что упрощает работу с помощью асинхронной модели программирования:
public static void Main()
{
var task = ExecuteQuery("1 Microsoft Way, Redmond, WA");
task.Wait();
Console.WriteLine(task.Result);
Console.ReadLine();
}
где
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 amp;amp;
response.ResourceSets != null amp;amp;
response.ResourceSets.Length > 0 amp;amp;
response.ResourceSets[0].Resources != null amp;amp;
response.ResourceSets[0].Resources.Length > 0)
{
return response.ResourceSets[0].Resources[0] as BingMapsRESTToolkit.Location;
}
return null;
}