Tom*_*Tom 1 c# core-location xamarin.ios async-await xamarin
我正在尝试测试Apple的前向地理编码服务的准确性,以涵盖我们的数据模型上的纬度/经度缺失或无效的罕见情况,但我们仍然知道物理地址.MonoTouch的提供CLGeocoder.GeocodeAddress(String, CLGeocodeCompletionHandler)以及GeocodeAddressAsync(String)但是当我打电话给他们的completionHandler不会被调用和异步方法永远不会返回.
我的应用程序日志中没有任何内容表明存在问题,并且将调用封装在try-catch块中并未显示任何异常.在项目选项中启用了地图集成.没有捕获网络流量(无论如何可能是SSL)我没有想法.
这是加载地标并尝试地理编码地址的代码:
private void ReloadPlacemarks()
{
// list to hold any placemarks which come back with empty/invalid coordinates
List<ServiceCallWrapper> geoList = new List<ServiceCallWrapper> ();
mapView.ClearPlacemarks ();
List<MKPlacemark> placemarks = new List<MKPlacemark>();
if (serviceCallViewModel.ActiveServiceCall != null) {
var serviceCall = serviceCallViewModel.ActiveServiceCall;
if (serviceCall.dblLatitude != 0 && serviceCall.dblLongitude != 0) {
placemarks.Add (serviceCall.ToPlacemark ());
} else {
// add it to the geocode list
geoList.Add (serviceCall);
}
}
foreach (var serviceCall in serviceCallViewModel.ServiceCalls) {
if (serviceCall.dblLatitude != 0 && serviceCall.dblLongitude != 0) {
placemarks.Add (serviceCall.ToPlacemark ());
} else {
//add it to the geocode list
geoList.Add (serviceCall);
}
}
if (placemarks.Count > 0) {
mapView.AddPlacemarks (placemarks.ToArray ());
}
if (geoList.Count > 0) {
// attempt to forward-geocode the street address
foreach (ServiceCallWrapper s in geoList) {
ServiceCallWrapper serviceCall = GeocodeServiceCallAddressAsync (s).Result;
mapView.AddPlacemark (serviceCall.ToPlacemark());
}
}
}
private async Task<ServiceCallWrapper> GeocodeServiceCallAddressAsync(ServiceCallWrapper s)
{
CLGeocoder geo = new CLGeocoder ();
String addr = s.address + " " + s.city + " " + s.state + " " + s.zip;
Console.WriteLine ("Attempting forward geocode for service call UID: " + s.call_uid + " with address: " + addr);
//app hangs on this
CLPlacemark[] result = await geo.GeocodeAddressAsync(addr);
//code updating latitude and longitude (omitted)
return s;
}
Run Code Online (Sandbox Code Playgroud)
你的问题是这一行:
ServiceCallWrapper serviceCall = GeocodeServiceCallAddressAsync (s).Result;
Run Code Online (Sandbox Code Playgroud)
通过调用Task<T>.Result,您正在导致死锁.我在我的博客上完整地解释了这一点,但它的要点是await(默认情况下)它会在产生控制时捕获"上下文",并将使用该上下文来完成该async方法.在这种情况下,"上下文"是UI上下文.因此,Result当响应进入时,UI线程被阻塞(等待),并且该async方法无法继续,因为它正在等待在UI线程上运行.
解决方案是一直使用async.换句话说,每更换Task<T>.Result和Task.Wait使用await:
private async Task ReloadPlacemarksAsync()
{
...
ServiceCallWrapper serviceCall = await GeocodeServiceCallAddressAsync (s);
...
}
Run Code Online (Sandbox Code Playgroud)
请注意,void ReloadPlacemarks现在是Task ReloadPlacemarksAsync,所以此更改会影响您的来电者.async将通过代码库"增长",这是正常的.有关详细信息,请参阅有关异步最佳实践的MSDN文章.
| 归档时间: |
|
| 查看次数: |
597 次 |
| 最近记录: |