如何等待QueryCompleted事件?

我创建了一个小测试应用程序来获取经度和纬度并将其转换为实际地址:

using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Device.Location; using System.Linq; using System.Net; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Navigation; using Microsoft.Phone.Controls; using Microsoft.Phone.Maps.Services; using Microsoft.Phone.Shell; using PhoneApp1.Resources; using Windows.Devices.Geolocation; namespace PhoneApp1 { public partial class MainPage : PhoneApplicationPage { private GeoCoordinate Location; public ObservableCollection Addresses { get; set; } // Constructor public MainPage() { InitializeComponent(); // Sample code to localize the ApplicationBar //BuildLocalizedApplicationBar(); } protected override async void OnNavigatedTo( NavigationEventArgs e ) { await GetLocation(); } public async Task GetLocation() { Location = await CoordinateConverter.GetLocation(); ReverseGeoCoding.StartReverseGeoCoding( Location ); //ReverseGeoCoding.done.WaitOne(); string Address = ReverseGeoCoding.Address; } } public static class ReverseGeoCoding { public static ObservableCollection Addresses = new ObservableCollection(); public static string Address; public static bool Completed; public static AutoResetEvent done = new AutoResetEvent( true ); public static void StartReverseGeoCoding( GeoCoordinate Location ) { Completed = false; var reverseGeocode = new ReverseGeocodeQuery(); reverseGeocode.GeoCoordinate = new GeoCoordinate( Location.Latitude, Location.Longitude ); reverseGeocode.QueryCompleted += ReverseGeocodeQueryCompleted; done.Reset(); reverseGeocode.QueryAsync(); } public static void ReverseGeocodeQueryCompleted( object sender, QueryCompletedEventArgs<System.Collections.Generic.IList> e ) { var reverseGeocode = sender as ReverseGeocodeQuery; if ( reverseGeocode != null ) { reverseGeocode.QueryCompleted -= ReverseGeocodeQueryCompleted; } //Microsoft.Phone.Maps.Services.MapAddress address; Addresses.Clear(); if ( !e.Cancelled ) { foreach ( var address in e.Result.Select( adrInfo => adrInfo.Information.Address ) ) { Addresses.Add( string.Format( "{0} {1}, {2} {3} {4}, {5}", address.HouseNumber, address.Street, address.City, address.State, address.PostalCode, address.Country ).Trim() ); } } if ( Addresses.Count > 0 ) { Address = Addresses[ 0 ].ToString(); } else { Address = ""; } done.Set(); Completed = true; } } public static class CoordinateConverter { public static GeoCoordinate ConvertGeocoordinate( Geocoordinate geocoordinate ) { return new GeoCoordinate ( geocoordinate.Latitude, geocoordinate.Longitude, geocoordinate.Altitude ?? Double.NaN, geocoordinate.Accuracy, geocoordinate.AltitudeAccuracy ?? Double.NaN, geocoordinate.Speed ?? Double.NaN, geocoordinate.Heading ?? Double.NaN ); } public static async Task GetLocation() { // Get current location. Geolocator myGeolocator = new Geolocator(); myGeolocator.DesiredAccuracy = PositionAccuracy.High; //myGeolocator.DesiredAccuracyInMeters = 50; Geocoordinate myGeocoordinate = null; try { Geoposition myGeoposition = await myGeolocator.GetGeopositionAsync ( maximumAge: TimeSpan.FromMinutes( 1 ), timeout: TimeSpan.FromSeconds( 10 ) ); myGeocoordinate = myGeoposition.Coordinate; } catch ( Exception ex ) { if ( (uint)ex.HResult == 0x80004004 ) { // the application does not have the right capability or the location master switch is off MessageBox.Show( "location is disabled in phone settings" ); } } if ( myGeocoordinate == null ) { return GeoCoordinate.Unknown; } GeoCoordinate myGeoCoordinate = CoordinateConverter.ConvertGeocoordinate( myGeocoordinate ); return myGeoCoordinate; } } } 

代码工作正常,即调用ReverseGeocodeQueryCompleted并正确计算地址。 但是,ReverseGeocodeQueryCompleted在GetLocation()完​​成后发生,并且分配给Address的地址为null。

我的问题是如何制作

 ReverseGeoCoding.StartReverseGeoCoding( Location ); 

等待完成:

 ReverseGeocodeQueryCompleted( object sender, QueryCompletedEventArgs<System.Collections.Generic.IList> e ) { .... } 

我尝试使用AutoResetEventWaitOne ,但整个线程停止,代码永远不会到达ReverseGeocodeQueryCompleted()

我愿意接受如何解决这个问题的建议。

EitanB

这是一个可以等待QuerryAsync的扩展方法:

 public static Task> QuerryTaskAsync(this ReverseGeocodeQuery reverseGeocode) { TaskCompletionSource > tcs=new TaskCompletionSource>(); EventHandler>> queryCompleted = null; queryCompleted=(send, arg) => { //Unregister event so that QuerryTaskAsync can be called several time on same object reverseGeocode.QueryCompleted -= queryCompleted; if (arg.Error != null) { tcs.SetException(arg.Error); }else if (arg.Cancelled) { tcs.SetCanceled(); } else { tcs.SetResult(arg.Result); } }; reverseGeocode.QueryCompleted += queryCompleted; reverseGeocode.QueryAsync(); return tcs.Task; } 

我修改了一点Benoit的答案看起来像这样:

  public static Task StartReverseGeoCodingAsync( System.Device.Location.GeoCoordinate Location ) { var reverseGeocode = new ReverseGeocodeQuery(); reverseGeocode.GeoCoordinate = new System.Device.Location.GeoCoordinate( Location.Latitude, Location.Longitude ); var tcs = new TaskCompletionSource(); EventHandler>> handler = null; handler = ( sender, args ) => { if ( args.Error != null ) { tcs.SetException( args.Error ); } else if ( args.Cancelled ) { tcs.SetCanceled(); } else { Addresses.Clear(); foreach ( var address in args.Result.Select( adrInfo => adrInfo.Information.Address ) ) { Addresses.Add( string.Format( "{0} {1}, {2} {3} {4}, {5}", address.HouseNumber, address.Street, address.City, address.State, address.PostalCode, address.Country ).Trim() ); } string Address = Addresses.Count > 0 ? Address = Addresses[ 0 ].ToString() : string.Empty; reverseGeocode.QueryCompleted -= handler; tcs.SetResult( Address ); } }; reverseGeocode.QueryCompleted += handler; reverseGeocode.QueryAsync(); return tcs.Task; } 

这将取代我的代码中的以下两个函数:

 #if never public static void StartReverseGeoCoding( GeoCoordinate Location ) { var reverseGeocode = new ReverseGeocodeQuery(); reverseGeocode.GeoCoordinate = new GeoCoordinate( Location.Latitude, Location.Longitude ); reverseGeocode.QueryCompleted += ReverseGeocodeQueryCompleted; reverseGeocode.QueryAsync(); } public static void ReverseGeocodeQueryCompleted( object sender, QueryCompletedEventArgs> e ) { var reverseGeocode = sender as ReverseGeocodeQuery; if ( reverseGeocode != null ) { reverseGeocode.QueryCompleted -= ReverseGeocodeQueryCompleted; } // Microsoft.Phone.Maps.Services.MapAddress address; Addresses.Clear(); if ( !e.Cancelled ) { foreach ( var address in e.Result.Select( adrInfo => adrInfo.Information.Address ) ) { Addresses.Add( string.Format( "{0} {1}, {2} {3} {4}, {5}", address.HouseNumber, address.Street, address.City, address.State, address.PostalCode, address.Country ).Trim() ); } } Address = ( Addresses.Count > 0 ) ? Addresses[ 0 ].ToString() : string.Empty; } 

万一

整体工作正常,再次感谢Benoit!

查找TaskCompletionSource以进行任务同步。

我稍后会写出更好的回复。 同时,请查看诺基亚开发者Wiki上的联系人服务的exception/等待 。