0

I tried to use Google .NET API to get verified user email, but app stops responding in line I marked with ****. The first time I run it opens browser and asks for my GMAIL, after selecting gmail it says now you can close browser window, but my desktop app will stop responding. Next time I run app it just stops responding unless I delete Google.Apis.Auth folder from AppData\Roaming :

        private async Task VerifyEmail()
        {
            UserCredential credential;
            credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
                new ClientSecrets
                {
                    ClientId = "xxxx.apps.googleusercontent.com",
                    ClientSecret = "xxxx-xxxxx"
                },
                new[] { Google.Apis.Oauth2.v2.Oauth2Service.Scope.UserinfoEmail },
                "user",
                CancellationToken.None,
                new FileDataStore("My.DataStore")
                );

            var initializer =
        new BaseClientService.Initializer()
        {
            HttpClientInitializer = credential,
            ApplicationName = "My App",
        };
            var oauthSerivce = new Google.Apis.Oauth2.v2.Oauth2Service(initializer);

            // app stops responding here **** :
            var userInfo = await oauthSerivce.Userinfo.Get().ExecuteAsync();
            MessageBox.Show(userInfo.Email);
        }
AVEbrahimi
  • 17,993
  • 23
  • 107
  • 210
  • 1
    "GoogleWebAuthorizationBroker.Authorize **Async** " ... await it. – Fildor Aug 21 '18 at 08:17
  • @Fildor it has .Result, same as await. – AVEbrahimi Aug 21 '18 at 08:21
  • _"it has .Result, same as await"_ - LOL. Wait until @StevenCleary sees this. – Fildor Aug 21 '18 at 08:22
  • @AVEbrahimi no it's not the same. Your code is deadlocking because your not `await`ing. Add an await at the right point(s) and it should work as expected. – Liam Aug 21 '18 at 08:23
  • added await (in question above too), still deadlock. :| – AVEbrahimi Aug 21 '18 at 09:03
  • changed var userInfo = await oauthSerivce.Userinfo.Get().ExecuteAsync(); to var userInfo = oauthSerivce.Userinfo.Get().ExecuteAsync().Result; now it works, but I don't understand it, would you please help @Fildor – AVEbrahimi Aug 21 '18 at 09:21
  • hmm, interesting... and strange. Did you try using `.ConfigureAwait(false)` ? – Fildor Aug 21 '18 at 09:27
  • I'd imagine that your not `await`ing up the chain. What calls `VerifyEmail` is this `async` and what about it's parent, and it's parent? All async methods need to be called async or you need to offload this work to a thread pool thread – Liam Aug 21 '18 at 10:01
  • @Liam all correct, thanks, now working using await. Please add your last comment as answer so other people use it. – AVEbrahimi Aug 21 '18 at 12:07

1 Answers1

1

Most of the content of this question is in the comments, so I've summarised below:

it has .Result, same as await.

.Result isn't the same as await. await marks the call as async and tells .Net to run this in an asynchronous context, without blocking. .Result blocks the thread and tries to obtain the result. You should (mostly) never block on async code like this, check out Stephen Cleary's blog Don't Block on Async Code.

added await (in question above too), still deadlock. :|

async code needs to be called in an async context. So you must make all the parent methods async as well. You can use a thread pool thread to get around this. But the best solutions is to make all your previous method calls async. This does mean than async tends o spread though your code base but that's the nature of the beast.

Liam
  • 27,717
  • 28
  • 128
  • 190