Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Microsoft.Graph GetAsync() hangs indefinitely

Introduction

I am developing an ASP.NET application which, among other things, is supposed to retrieve users from Azure Active Directory. For this purpose, I am using the Microsoft Graph version 1.14.0 preview library, which can be found here.

As this library only provides asynchronous methods for retrieving users, I am using the following (pseudo) code to run it synchronously.

string userPrincipalName = "[email protected]";
var task = Task.Run(async () => await _graphServiceClient.Users[userPrincipalName].Request().GetAsync());

while (!task.IsCompleted)
     Thread.Sleep(200);

User retrievedUser = task.Result;

Problem

The problem I am facing right now is that upon calling this piece of code from the ASP.NET application, task.IsCompleted remains forever false. Now here is the strange part which I can not wrap my head around: the code runs perfectly in both a Console Application and a Unit Test (using NUnit).

One might think that the GraphServiceClient instance is built differently in these versions, but I am 100% positive that it is not. The information that makes it up is loaded from a database, and the code in the Unit Test is exactly the same as the code in the controller of the ASP.NET application. Using the Unit Test, the above code is executed in about 1.5 seconds. In the ASP.NET application, I left it running for as long as 30 minutes without any results, no errors, no time-outs, nothing at all.

I realize this might be a bit of a niche problem, but I do hope that someone has run into the same problem and was able to resolve it.

Update

I managed to resolve this issue. Weirdly enough, converting all my methods to async Tasks did not work, as even await kept hanging. I do however not fully understand why my solution works now. It looks as though my pseudo-code was not fully accurate, and the solution lies therein.

Attempt #1 (does not work)

This code remains forever in while (!runTask.IsCompleted).

object GetResult<TResult>(Task<TResult> task)
{
    using (task)
    using (var runTask = Task.Run(async () => await task))
    {
        while (!runTask.IsCompleted)
            Thread.Sleep(SleepTime);

        if (runTask.Exception != null)
            throw runTask.Exception.InnerException ?? runTask.Exception;

        return runTask.Result;
    }
}

User GetUser(string userPrincipalName)
{   
    return (User)GetResult(_graphServiceClient.Users[userPrincipalName].Request().GetAsync());
}

Attempt #2 (does not work)

This method keeps hanging after executing the await line.

async Task<User> GetUser(string userPrincipalName)
{
    User user = await _graphServiceClient.Users[userPrincipalName].Request().GetAsync();
    return user;
}

Attempt #3 (works)

This code is basically the same as the code in attempt #1, the only difference being that it does not use the GetResult method, but it does use the exact same approach as GetResult.

User GetUser(string userPrincipalName)
{
    using(var task = Task.Run(async () => await _graphServiceClient.Users[userPrincipalName].Request().GetAsync()))
    {
        while (!task.IsCompleted)
            Thread.Sleep(200);

        return task.Result;
    }
}

While this approach might not be considered best practice, it does work. I am extremely puzzled about why this approach works, because the code in attempt #1 does not, and it is virtually the same code. Can anybody explain why that is?

like image 485
Johan Wintgens Avatar asked Mar 11 '19 15:03

Johan Wintgens


2 Answers

I had the same issue (see here). I solved it by reverting Microsoft.Graph and Microsoft.Graph.Core version 1.12.0.

like image 112
mr.coffee Avatar answered Sep 29 '22 14:09

mr.coffee


Avoid using Result in functions but deal directly with users

User user = await gServiceClient.Users[ID].Request().GetAsync();
like image 24
Badr Bellaj Avatar answered Sep 29 '22 12:09

Badr Bellaj