OneBigQuestion
OneBigQuestion

Reputation: 100

Issue with async Task<T> in xamarin forms

I'm trying to use the Azure media services with REST api, in a xamarin shared project on visual studio 2013. This is the code i use to get the access token.

public HttpFactory()
{
    string token = GetToken(serviceURI).Result;
    //some more methods also async tasks
}

private async Task<string> GetToken(Uri serviceUri)
{
    HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(serviceURI);
    request.Accept = "application/json";
    request.Method = "GET";
    request.Headers["Host"] = "media.windows.net";
    request.Headers["x-ms-version"] = "2.9";
    request.Headers["Authorization"] = "Bearer " + token;
    var response = (HttpWebResponse) await request.GetResponseAsync();

    if (response.StatusCode == HttpStatusCode.MovedPermanently)
    {
        serviceURI = new Uri(response.Headers["Location"]);
        HttpWebRequest req = ( HttpWebRequest)WebRequest.Create(serviceURI);
        var res = (HttpWebResponse)await req.GetResponseAsync();

        using (Stream responseStream = res.GetResponseStream())
        {
            using (StreamReader reader = new StreamReader(responseStream))
            {
                string str = reader.ReadToEnd();
                // var test = JsonConvert.DeserializeObject(str);
                JToken jtoken = JsonConvert.DeserializeObject<JToken>(str);
                 return jtoken["access_token"].Value<string>();

            }
        }
    }
    return "";
}

But when the compiler reaches -

var response = (HttpWebResponse) await request.GetResponseAsync();

it skips the rest of the code, and i never get the response. I know the code is working - because it works just fine without the task, in a async void method.

Anyone knows how to fix this, or am i doing something wrong? I also tried this in vs2015 but its the same.

Upvotes: 2

Views: 4776

Answers (1)

i3arnon
i3arnon

Reputation: 116538

You have a deadlock over the UI thread.

You're blocking the thread with Task.Result when it is needed to complete the async method which will complete the task that it's waiting on.

That's why you shouldn't block synchronously on asynchronous code. You should await the task returned from GetToken instead:

string token = await GetToken(serviceURI);

If you can't use async in that method, either move that logic to a different method (e.g. OnLoad event handler).

Another solution would be to use ConfigureAwait on the GetResponseAsync task and so the rest of the method wouldn't run on the UI thread, avoiding the deadlock:

var response = (HttpWebResponse) await request.GetResponseAsync().ConfigureAwait(false);

Upvotes: 8

Related Questions