Bug 60944 - Xamarin.GooglePlayServices.Location SettingsClient.CheckLocationSettingsAsync works only on an 'async' method. Can't be waited synchronously with task.Wait();
Summary: Xamarin.GooglePlayServices.Location SettingsClient.CheckLocationSettingsAsync...
Alias: None
Product: Components
Classification: Xamarin
Component: Xamarin Components ()
Version: Staging (addons.xamstage.com)
Hardware: PC Windows
: --- normal
Target Milestone: ---
Assignee: Jon Dick
Depends on:
Reported: 2017-12-01 15:16 UTC by apujadas
Modified: 2017-12-01 17:30 UTC (History)
1 user (show)

Is this bug a regression?: ---
Last known good build:

Project with both sync and async calls to the SettingsClient.CheckLocationSettingsAsync showing the hang. (6.35 MB, application/x-zip-compressed)
2017-12-01 15:16 UTC, apujadas

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:

Description apujadas 2017-12-01 15:16:53 UTC
Created attachment 25885 [details]
Project with both sync and async calls to the SettingsClient.CheckLocationSettingsAsync showing the hang.

When i'm trying to use the Android.Gms.Location SettingsClient.CheckLocationSettingsAsync (Xamarin.GooglePlayServices.Location 60.1142.0-rc1, downloaded from NuGet, 'Include Pre-Release' checked) in an synchronous manner by task.Wait() and then using the result with task.Result, the app hangs in the '.Wait()' method. This does not happen when SettingsClient.CheckLocationSettingsAsync is awaited in a async method. To show this behavior, i've attached a sample project where this issue can be reproduced easily.

Steps to Reproduce:
0) Add from NuGet, dependencies to Xamarin.GooglePlayServices.Location version 60.1142.0-rc1
1) Make a synchronous call to SettingsClient.CheckLocationSettingsAsync and wait to the task to be completed.

Actual Results: The app hangs in the 'Wait()' method.

Expected Results: Blocking the calling thread in the 'Wait()' method, the task must finish in a acceptable time. 

Microsoft Visual Studio Community 2017 
Version 15.4.4
Microsoft .NET Framework
Version 4.6.01586

Installed Version: Community

Visual Basic 2017   00369-60000-00001-AA490
Microsoft Visual Basic 2017

Visual C# 2017   00369-60000-00001-AA490
Microsoft Visual C# 2017

Visual C++ 2017   00369-60000-00001-AA490
Microsoft Visual C++ 2017

Visual F# 4.1   00369-60000-00001-AA490
Microsoft Visual F# 4.1

Application Insights Tools for Visual Studio Package   8.9.00809.2
Application Insights Tools for Visual Studio

ASP.NET and Web Tools 2017   15.0.30925.0
ASP.NET and Web Tools 2017

ASP.NET Core Razor Language Services   1.0
Provides languages services for ASP.NET Core Razor.

ASP.NET Web Frameworks and Tools 2017   5.2.50921.0
For additional information, visit https://www.asp.net/

Azure App Service Tools v3.0.0   15.0.30915.0
Azure App Service Tools v3.0.0

Common Azure Tools   1.10
Provides common services for use by Azure Mobile Services and Microsoft Azure Tools.

Cookiecutter   3.0.17310.2
Provides tools for finding, instantiating and customizing templates in cookiecutter format.

JavaScript Language Service   2.0
JavaScript Language Service

JavaScript Project System   2.0
JavaScript Project System

JavaScript UWP Project System   2.0
JavaScript UWP Project System

Merq   1.1.17-rc (cba4571)
Command Bus, Event Stream and Async Manager for Visual Studio extensions.

Microsoft Azure Tools   2.9
Microsoft Azure Tools for Microsoft Visual Studio 2017 - v2.9.50719.1

Microsoft Continuous Delivery Tools for Visual Studio   0.3
Simplifying the configuration of continuous build integration and continuous build delivery from within the Visual Studio IDE.

Microsoft JVM Debugger   1.0
Provides support for connecting the Visual Studio debugger to JDWP compatible Java Virtual Machines

Microsoft MI-Based Debugger   1.0
Provides support for connecting Visual Studio to MI compatible debuggers

Microsoft Visual C++ Wizards   1.0
Microsoft Visual C++ Wizards

Microsoft Visual Studio VC Package   1.0
Microsoft Visual Studio VC Package

Mono Debugging for Visual Studio   4.7.4-pre (c2d89eb)
Support for debugging Mono processes with Visual Studio.

Node.js Tools   1.4.10918.1
Adds support for developing and debugging Node.js apps in Visual Studio

NuGet Package Manager   4.4.0
NuGet Package Manager in Visual Studio. For more information about NuGet, visit http://docs.nuget.org/.

Python   3.0.17310.2
Provides IntelliSense, projects, templates, debugging, interactive windows, and other support for Python developers.

Python - Django support   3.0.17310.2
Provides templates and integration for the Django web framework.

Python - IronPython support   3.0.17310.2
Provides templates and integration for IronPython-based projects.

Python - Profiling support   3.0.17310.2
Profiling support for Python projects.

SQL Server Data Tools   15.1.61707.200
Microsoft SQL Server Data Tools

TypeScript tools for Visual Studio

Visual Studio Code Debug Adapter Host Package   1.0
Interop layer for hosting Visual Studio Code debug adapters in Visual Studio

Visual Studio Tools for Universal Windows Apps   15.0.27004.2008
The Visual Studio Tools for Universal Windows apps allow you to build a single universal app experience that can reach every device running Windows 10: phone, tablet, PC, and more. It includes the Microsoft Windows 10 Software Development Kit.

VisualStudio.IoT   1.0
Package with IoT components for Visual Studio

VisualStudio.Mac   1.0
Mac Extension for Visual Studio

VisualSVN   6.0.4
Integration with Subversion version control. For more information about VisualSVN, see the VisualSVN website at http://www.visualsvn.com
Copyright © 2017 VisualSVN Software Ltd. All rights reserved.

VSColorOutput   2.5.1
Color output for build and debug windows - http://mike-ward.net/vscoloroutput

Web Extension Pack 2017   15.0.2
The easiest way to set up Visual Studio for the ultimate web development experience.

Xamarin (34c1b6c)
Visual Studio extension to enable development for Xamarin.iOS and Xamarin.Android.

Xamarin.Android SDK (HEAD/c2a33d8ea)
Xamarin.Android Reference Assemblies and MSBuild support.

Xamarin.iOS and Xamarin.Mac SDK (51128b8)
Xamarin.iOS and Xamarin.Mac Reference Assemblies and MSBuild support.
Comment 1 apujadas 2017-12-01 15:41:17 UTC
After i posted this, i realized that SettingsClient.CheckLocationSettingsAsync 'doesn't like' to block the UI thread with the 'Wait()' method. To prove this, i've putted the synchronous way (with the 'Wait()') in a Task. This executed flawlessly.

Nonetheless, there's no way to determine this behavior by API design. SettingsClient.CheckLocationSettingsAsync returns a Task and i thought that i could wait it to finish properly, without any other implications. Any docs on this?
Comment 2 Jon Dick 2017-12-01 16:24:31 UTC
It seems like you've already figured this out.

Basically Google doesn't want you blocking the UI thread for these calls.  The SettingsClient.CheckLocationSettings method returns an Android.Gms.Tasks.Task type which looks very similar to our System.Threading.Tasks.Task but isn't quite the same.  The Android.Gms.Tasks.Task is not typically supposed to be waited synchronously on the UI thread, and Google enforces that, at least in some cases (including this).

So, our CheckLocationSettingsAsync method is returning a System.Threading.Tasks.Task which basically wraps Android.Gms.Tasks.Task by calling .AddOnCompleteListener and triggering a TaskCompletionSource when the callback is invoked.

As is with any System.Threading.Tasks.Task, a Task in this case doesn't necessarily mean thread, so while you attempt to .Wait() on this task on the UI thread, the execution would still be blocking the UI Thread, and then Google is unhappy.

The recommendation here would be to actually use this method via await if you can, or you can of course as you figured out, run this inside of another task.

We should definitely add some docs around this case.
Comment 3 apujadas 2017-12-01 17:30:03 UTC
Sorry for any inconvenience and thanks for your time Jonathan. Really looking forward for those docs then.