C# 正在等待GetGeopositionAsync()的结果

C# 正在等待GetGeopositionAsync()的结果,c#,.net,geolocation,task-parallel-library,async-await,C#,.net,Geolocation,Task Parallel Library,Async Await,我正在开发WinPhone 8应用程序。 此应用程序上有一个按钮“发送短信”。 当用户单击此按钮时,应发生两件事: (方法A)获取当前位置的地理坐标(使用Geolocator和GetGeopositionAsync) (方法B)编写并发送一条短信,其中地理坐标是身体的一部分 问题在于:GetGeopositionAsync是一种异步方法。在检测到坐标(需要几秒钟)之前,会发送SMS(当然没有坐标) 我如何告诉方法2等待坐标可用 好的,这是我的代码: 当用户按下按钮时,坐标由第一种方法确定,第二种

我正在开发WinPhone 8应用程序。 此应用程序上有一个按钮“发送短信”。 当用户单击此按钮时,应发生两件事:

  • (方法A)获取当前位置的地理坐标(使用Geolocator和GetGeopositionAsync)
  • (方法B)编写并发送一条短信,其中地理坐标是身体的一部分
  • 问题在于:GetGeopositionAsync是一种异步方法。在检测到坐标(需要几秒钟)之前,会发送SMS(当然没有坐标)

    我如何告诉方法2等待坐标可用

    好的,这是我的代码:

    当用户按下按钮时,坐标由第一种方法确定,第二种方法发送短信,短信正文中包含坐标:

    private void btnSendSms_Click(object sender, RoutedEventArgs e)
    {
        GetCurrentCoordinate();  // Method 1
        // -> Gets the coordinates
    
        SendSms();               // Method 2
        // Sends the coordinates within the body text
    }
    
    第一个方法GetCurrentCoordinate()如下所示:

            ...
    private GeoCoordinate MyCoordinate = null;
    private ReverseGeocodeQuery MyReverseGeocodeQuery = null;
    private double _accuracy = 0.0;
            ...
    
    private async void GetCurrentCoordinate()
    {
        Geolocator geolocator = new Geolocator();
        geolocator.DesiredAccuracy = PositionAccuracy.High;
    
        try
        {
            Geoposition currentPosition = await geolocator.GetGeopositionAsync(
                TimeSpan.FromMinutes(1), 
                TimeSpan.FromSeconds(10));
            lblLatitude.Text = currentPosition.Coordinate.Latitude.ToString("0.000");
            lblLongitude.Text = currentPosition.Coordinate.Longitude.ToString("0.000");
            _accuracy = currentPosition.Coordinate.Accuracy;
            MyCoordinate = new GeoCoordinate(
                currentPosition.Coordinate.Latitude, 
                currentPosition.Coordinate.Longitude);
            if (MyReverseGeocodeQuery == null || !MyReverseGeocodeQuery.IsBusy)
            {
                MyReverseGeocodeQuery = new ReverseGeocodeQuery();
                MyReverseGeocodeQuery.GeoCoordinate = new GeoCoordinate(
                    MyCoordinate.Latitude, 
                    MyCoordinate.Longitude);
                MyReverseGeocodeQuery.QueryCompleted += ReverseGeocodeQuery_QueryCompleted;
                MyReverseGeocodeQuery.QueryAsync();
            }
        }
        catch (Exception)
        { // Do something }
    }
    
    private void ReverseGeocodeQuery_QueryCompleted(object sender, 
                                                    QueryCompletedEventArgs<IList<MapLocation>> e)
    {
        if (e.Error == null)
        {
            if (e.Result.Count > 0)
            {
                MapAddress address = e.Result[0].Information.Address;
                lblCurrAddress.Text = address.Street + " " + address.HouseNumber + ",\r" +
                    address.PostalCode + " " + address.City + ",\r" +
                    address.Country + " (" + address.CountryCode + ")";
    
                }
            }
        }
    }
    
    问题是,当方法SendSms()设置SmsComposeTask对象时,所有这些文本框(lblationate、lblLongitude、lblCurrAddress)仍然为空。


    我必须确保在方法SendSms()启动之前已经设置了文本框。

    除非是UI事件处理程序,否则几乎不应该将方法标记为
    async void
    。您正在调用一个异步方法,而不等待它结束。您基本上是并行调用这两个方法,因此很清楚为什么坐标不可用

    您需要使
    GetCurrentCoordinate
    返回一个等待的任务并等待它,如下所示:

    private async Task GetCurrentCoordinateAsync()
    {
        //....
    }
    
    private async void btnSendSms_Click(object sender, RoutedEventArgs e)
    {
        await GetCurrentCoordinateAsync();
        // You'll get here only after the first method finished asynchronously.
        SendSms();
    }
    
    private async void btnSendSms_Click(object sender, RoutedEventArgs e)
    {
      await GetCurrentCoordinate();
      SendSms();
    }
    

    除非方法是UI事件处理程序,否则几乎不应该将其标记为async void。您正在调用一个异步方法,而不等待它结束。您基本上是并行调用这两个方法,因此很清楚为什么坐标不可用

    您需要使
    GetCurrentCoordinate
    返回一个等待的任务并等待它,如下所示:

    private async Task GetCurrentCoordinateAsync()
    {
        //....
    }
    
    private async void btnSendSms_Click(object sender, RoutedEventArgs e)
    {
        await GetCurrentCoordinateAsync();
        // You'll get here only after the first method finished asynchronously.
        SendSms();
    }
    
    private async void btnSendSms_Click(object sender, RoutedEventArgs e)
    {
      await GetCurrentCoordinate();
      SendSms();
    }
    

    这是您应该避免
    async void
    的主要原因之一
    void
    对于
    async
    方法来说是一种非常不自然的返回类型

    首先,将
    GetCurrentCoordinate
    设置为
    async任务
    方法,而不是
    async void
    。然后,您可以将单击处理程序更改为如下所示:

    private async Task GetCurrentCoordinateAsync()
    {
        //....
    }
    
    private async void btnSendSms_Click(object sender, RoutedEventArgs e)
    {
        await GetCurrentCoordinateAsync();
        // You'll get here only after the first method finished asynchronously.
        SendSms();
    }
    
    private async void btnSendSms_Click(object sender, RoutedEventArgs e)
    {
      await GetCurrentCoordinate();
      SendSms();
    }
    

    单击处理程序是
    async void
    ,这只是因为事件处理程序必须返回
    void
    。但是您应该在所有其他代码中真正努力避免
    async void

    这是您应该避免
    async void
    的主要原因之一
    void
    对于
    async
    方法来说是一种非常不自然的返回类型

    首先,将
    GetCurrentCoordinate
    设置为
    async任务
    方法,而不是
    async void
    。然后,您可以将单击处理程序更改为如下所示:

    private async Task GetCurrentCoordinateAsync()
    {
        //....
    }
    
    private async void btnSendSms_Click(object sender, RoutedEventArgs e)
    {
        await GetCurrentCoordinateAsync();
        // You'll get here only after the first method finished asynchronously.
        SendSms();
    }
    
    private async void btnSendSms_Click(object sender, RoutedEventArgs e)
    {
      await GetCurrentCoordinate();
      SendSms();
    }
    

    单击处理程序是
    async void
    ,这只是因为事件处理程序必须返回
    void
    。但您应该真正努力避免在所有其他代码中出现
    异步无效。

    这里有两件事您做错了:

  • 在需要等待时使用void returning
    async
    方法。这是不好的,因为您不能等待这些方法的执行,并且只能在无法使方法返回
    Task
    Task
    时使用。这就是为什么在调用
    SendSms
    时,文本框中看不到任何内容
  • 混合UI和非UI代码。您应该在UI和非UI代码之间传输数据,以避免具有不同职责的代码之间的紧密耦合。它还使阅读和调试代码变得容易
  • ReverseGeocodeQuery
    没有可等待的异步API,但:


    这有意义吗?

    这里有两件事你做错了:

  • 在需要等待时使用void returning
    async
    方法。这是不好的,因为您不能等待这些方法的执行,并且只能在无法使方法返回
    Task
    Task
    时使用。这就是为什么在调用
    SendSms
    时,文本框中看不到任何内容
  • 混合UI和非UI代码。您应该在UI和非UI代码之间传输数据,以避免具有不同职责的代码之间的紧密耦合。它还使阅读和调试代码变得容易
  • ReverseGeocodeQuery
    没有可等待的异步API,但:


    这有意义吗?

    您应该尝试使用代码自己解决问题。您应该尝试使用代码自己解决问题。非常感谢。就这样,非常感谢。就这样。