【问题标题】:Await of MapLocationFinder.FindLocationsAtAsync never ends等待 MapLocationFinder.FindLocationsAtAsync 永远不会结束
【发布时间】:2019-05-21 09:16:17
【问题描述】:

在 MapLocationFinder 的等待下,我的程序仍在运行,即使在尝试使用 Application.Current.Shutdown(); 关闭它之后也是如此。我是初学者。

我已经尝试使用 CancellationToken 或将其作为任务运行。但我不知道我是否以正确的方式做到了这一点。我尝试了几个小时的不同想法,但没有任何效果。

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;
    }

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

【问题讨论】:

  • 如果所有这些都在事件处理程序(或单独的线程)中完成,也许使用CancellationTokenSource 会起作用?

标签: c# wpf uwp async-await task


【解决方案1】:

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

我已经运行了您的代码,但我无法重现该问题,我可以得到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);
}

【讨论】:

  • 您好!感谢您的回答。 var source = new CancellationTokenSource(400); MapLocationFinderResult result = await MapLocationFinder.FindLocationsAtAsync(geopoint, MapLocationDesiredAccuracy.Low).AsTask(source.Token); 取消这个任务就够了吗?因为这也行不通
  • 尝试设置 1500 毫秒延迟。
  • 问题是他完成了任务,但 CancellationToken 仍然没有结束任务,我无法正确关闭我的程序。您使用哪个 UWP SDK 版本?
  • 有趣的是:当我删除 MapLocationDesiredAccuracy 时,他并没有完成工作(顺便说一句,我的机器永远不会低)。所以他不再等待这个任务(结束它?),然后继续执行其余的代码。但仍然:当我关闭我的程序时,后台的东西仍然运行。这仅在使用此行时。当我删除 MapLocationFinderResult 程序关闭可靠。这真是令人绝望。
  • 我项目的目标版本是17763,最小版本是17134。
【解决方案2】:

看起来这是一个已知的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();
     }
}

【讨论】:

  • 不错的“解决方法”,仅在必要时终止应用程序。好的! :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多