[英]ThreadPool.QueueUserWorkItem Causes App to Hang Until Finished
[英]Instantiating LocationService in OnNavigatedToAsync causes app to hang
我目前正在使用UWP和Template10编写位置感知的MVVM应用程序。 作为此应用程序的一部分,我正在显示一个使用MapControl的地图页面,这需要显示用户的当前位置。
我正在尝试利用作为Template10框架一部分的LocationService (尽管该服务当前未包含在NuGet包中)。 我遇到的问题是,由于此MSDN文章中提到的约束,即,我无法调用此服务来获取页面的OnNavigatedToAsync方法中用户的当前位置:
访问用户的位置之前,请调用RequestAccessAsync。 那时,您的应用必须位于前台,并且必须从UI线程调用RequestAccessAsync。 在用户向您的应用授予其位置权限之前,您的应用无法访问位置数据。
这是因为向用户显示了一个对话框,询问允许使用设备位置的权限-但由于我们不在UI线程上,因此该应用程序仅挂起。
页面完成加载并准备就绪后,是否可以调用另一种方法(将调用LocationService )? 我尝试从页面的Loaded事件中挂入命令调用,但是在那里也发生了相同的问题。
我正在尝试利用作为Template10框架一部分的LocationService(尽管该服务当前未包含在NuGet包中)。
您这个LocationService
是什么意思? 我找不到与此有关的任何文档。 我只是在您提供的文档中使用了Geolocator来测试您的问题,所以我无法复制它。
这是因为向用户显示了一个对话框,询问允许使用设备位置的权限-但由于我们不在UI线程上,因此该应用程序仅挂起。
不,据说在访问用户位置之前必须先调用RequestAccessAsync
方法,并且必须从UI线程中调用,如果在OnNavigatedToAsync
调用此RequestAccessAsync
方法,则从UI线程中调用该应用程序将不会挂起。
这是我的示例,我创建了一个空的汉堡模板10项目,并在“详细信息”页面中:
首先添加4 TextBlock
以在xaml中显示状态和位置:
<!-- content -->
<ScrollViewer Padding="12,8,0,0" RelativePanel.AlignBottomWithPanel="True"
RelativePanel.AlignLeftWithPanel="True"
RelativePanel.AlignRightWithPanel="True"
RelativePanel.Below="pageHeader"
VerticalScrollBarVisibility="Auto">
<StackPanel>
<TextBlock Style="{StaticResource TitleTextBlockStyle}" Text="You passed:" />
<TextBlock Style="{StaticResource SubtitleTextBlockStyle}" Text="{x:Bind ViewModel.Value, Mode=OneWay, FallbackValue=DesigntimeValue}" />
<TextBlock Style="{StaticResource SubtitleTextBlockStyle}" Text="{x:Bind ViewModel.Status,Mode=OneWay}" />
<TextBlock Style="{StaticResource SubtitleTextBlockStyle}" Text="{x:Bind ViewModel.Latitude, Mode=OneWay}" />
<TextBlock Style="{StaticResource SubtitleTextBlockStyle}" Text="{x:Bind ViewModel.Longitude, Mode=OneWay}" />
<TextBlock Style="{StaticResource SubtitleTextBlockStyle}" Text="{x:Bind ViewModel.Accuracy, Mode=OneWay}" />
</StackPanel>
</ScrollViewer>
ViewModel中的部分代码:
public override async Task OnNavigatedToAsync(object parameter, NavigationMode mode, IDictionary<string, object> suspensionState)
{
Value = (suspensionState.ContainsKey(nameof(Value))) ? suspensionState[nameof(Value)]?.ToString() : parameter?.ToString();
StartTracking();
await Task.CompletedTask;
}
private async void StartTracking()
{
// Request permission to access location
var accessStatus = await Geolocator.RequestAccessAsync();
switch (accessStatus)
{
case GeolocationAccessStatus.Allowed:
_cts = new CancellationTokenSource();
CancellationToken token = _cts.Token;
_geolocator = new Geolocator { DesiredAccuracyInMeters = _desireAccuracyInMetersValue };
Geoposition pos = await _geolocator.GetGeopositionAsync().AsTask(token);
UpdateLocationData(pos);
// Subscribe to PositionChanged event to get updated tracking positions
_geolocator.PositionChanged += OnPositionChanged;
// Subscribe to StatusChanged event to get updates of location status changes
_geolocator.StatusChanged += OnStatusChanged;
break;
case GeolocationAccessStatus.Denied:
break;
case GeolocationAccessStatus.Unspecified:
break;
}
}
其他代码可以参考官方地理位置示例 。
页面加载完成并准备就绪后,是否可以调用另一种方法(将调用LocationService)?
我认为问题在于您需要检查导致应用程序挂起的确切原因。 如果是LocationService
的问题,可以在评论中发布该服务的文档吗?
更新:
如果您阅读此LocationService
的源代码,并且使用代码var locationService = new LocationService();var pos = locationService.Position;
,则可以找到它将Geolocation
API打包到一个服务中var locationService = new LocationService();var pos = locationService.Position;
,那么StartTracking()
方法中的大多数代码都是无用的,它们只是创建了另一个Geolocator
,并尝试获取位置,并在位置再次更改时获取通知,就像服务一样。 但是仍然需要RequestAccessAsync
,并且必须在新建LocationService
实例之前调用RequestAccessAsync
,因此可以这样编写代码:
public override async Task OnNavigatedToAsync(object parameter, NavigationMode mode, IDictionary<string, object> suspensionState)
{
Value = (suspensionState.ContainsKey(nameof(Value))) ? suspensionState[nameof(Value)]?.ToString() : parameter?.ToString();
var accessStatus = await Geolocator.RequestAccessAsync();
var locationService = new LocationService();
var pos = locationService.Position;
//StartTracking();
await Task.CompletedTask;
}
刚刚测试,效果很好。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.