MapLocationFinder.FindLocationsAtAsync的等待永无止境

时间:2018-12-20 20:31:56

标签: c# wpf uwp async-await task

在等待MapLocationFinder的情况下,即使试图使用Application.Current.Shutdown();将其关闭,我的程序仍会运行。我是初学者。

我已经尝试使用CancellationToken或将其作为Task运行。但是我不知道我是否以正确的方式做到了。我花了几个小时尝试了不同的想法,但对我没有任何帮助。

private async Task GetLocation()
    {
        var accesStatus = await Geolocator.RequestAccessAsync();
        switch (accesStatus)
        {
            case GeolocationAccessStatus.Allowed:
                // locate user
                var locator = new Windows.Devices.Geolocation.Geolocator();
                var location = await locator.GetGeopositionAsync();
                var position = location.Coordinate.Point.Position;

                // get city name
                Geopoint geopoint = new Geopoint(new BasicGeoposition
                {
                    Latitude = position.Latitude,
                    Longitude = position.Longitude
                });

问题在这里出现

                MapLocationFinderResult result = await MapLocationFinder.FindLocationsAtAsync(geopoint, MapLocationDesiredAccuracy.Low);

                if (result.Status == MapLocationFinderStatus.Success)
                {
                    locationBlock.Text = "City: " + result.Locations[0].Address.Town;
                }

问题结束了,剩下的只是针对上下文的

                // calculate time
                int[] sun = SunDate.CalculateSunriseSunset(51.434406, 6.762329);
                var sunrise = new DateTime(1, 1, 1, sun[0] / 60, sun[0] - (sun[0] / 60) * 60, 0);
                var sunset = new DateTime(1, 1, 1, sun[1] / 60, sun[1] - (sun[1] / 60) * 60, 0);

                //fit UI
                lightStartBox.Text = sunrise.Hour.ToString();
                darkStartBox.Text = sunset.Hour.ToString();

                // apply settings
                lightStartBox.IsEnabled = false;
                darkStartBox.IsEnabled = false;
                break;

            case GeolocationAccessStatus.Denied:
                locationCheckBox.IsChecked = false;
                locationBlock.Text = "The App needs permission to location";
                await Windows.System.Launcher.LaunchUriAsync(new Uri("ms-settings:privacy-location"));
                break;

            case GeolocationAccessStatus.Unspecified:
                locationCheckBox.IsChecked = false;
                locationBlock.Text = "The App needs permission to location";
                await Windows.System.Launcher.LaunchUriAsync(new Uri("ms-settings:privacy-location"));
                break;
        }
        return;
    }

如果我关闭程序,它也应该结束等待任务。更好:应该在他获得信息后结束手术。

2 个答案:

答案 0 :(得分:0)

  

如果我关闭程序,它也应该结束等待任务。更好:应该在他获得信息后结束手术。

我已经运行了您的代码,但是我无法重现该问题,我可以以较低的延迟获得MapLocationFinderResult。我发现您使用了MapLocationDesiredAccuracy.Low参数。它将利用地图磁盘缓存来获取准确的城市信息。映射磁盘缓存可能会导致此问题。您可以尝试使用MapLocationDesiredAccuracy.High参数。

如您所见,FindLocationsAtAsyncIAsyncOperation方法。因此,您可以手动取消它或设置超时取消令牌。

例如

private IAsyncOperation<string> GetAsyncOperation()
{
    return AsyncInfo.Run<string>(
       (token) => // CancellationToken token
           Task.Run<string>(
               () =>
               {
                   token.WaitHandle.WaitOne(3000);
                   token.ThrowIfCancellationRequested();     
                   return "hello";
               },
               token));
}

private IAsyncOperation<string> operation;

private async void Button_Click(object sender, RoutedEventArgs e)
{
    try
    {
        operation = GetAsyncOperation();
        var res = await operation;
    }
    catch (Exception)
    {

        System.Diagnostics.Debug.WriteLine("method end");
    }

}
private void Cancel_Button_Click(object sender, RoutedEventArgs e)
{
    operation?.Cancel();
}

设置超时

private async void Button_Click(object sender, RoutedEventArgs e)
{
  var source = new CancellationTokenSource(4000);
  var res = await GetAsyncOperation().AsTask(source.Token);
}

答案 1 :(得分:0)

看起来这是已知的bug

要解决此问题,我最终在我的App类上设置了一个静态标志,以便在应用关闭时将强制终止该进程。

// Before call to MapLocationFinder.FindLocationsAsync()
App.RequiresProcessKill = true;

然后在关闭过程中(即在您主窗口的OnClosed方法中)强制关闭了该应用程序:

protected override void OnClosed(EventArgs e)
{
    base.OnClosed(e);
     if (App.RequiresProcessKill)
     {
         var self = Process.GetCurrentProcess();
         self.Kill();
     }
}