Sir
Sir

Reputation: 8280

HTTP Client with Unity, application hangs

I have a pretty basic script in my Unity game which is trying to submit form data in POST to a server. But unity seems to freeze/hang indefinitely. I am confused why this is happening and so i don't know how to solve the problem.

I made my code loosely following this article: https://learn.microsoft.com/en-us/dotnet/csharp/tutorials/console-webapiclient#making-web-requests

My server does receive the request and does write one back. But because unity is frozen its not really usable at the moment.

My class looks like this:

public class HTTPManager : MonoBehaviour
{
    private static HttpClient client = new HttpClient();
    private void Awake()
    {
        client.BaseAddress = new Uri("http://localhost:8080/");
        ProcessRepositories().Wait();
    }

    private async Task ProcessRepositories()
    {
        client.DefaultRequestHeaders.Accept.Clear();

        FormUrlEncodedContent content = new FormUrlEncodedContent(new[]
        {
            new KeyValuePair<string, string>("u", "test")
        });

        //this goes to http://localhost:8080/hello with POST u=test
        HttpResponseMessage result = await client.PostAsync("hello",content);

        Debug.Log("Is Success: "+result.IsSuccessStatusCode);
        Debug.Log("Status code: "+result.StatusCode);
        Debug.Log("Reason Phrase: "+result.ReasonPhrase);
        Debug.Log("Headers: "+result.Headers);
        Debug.Log("Content: "+result.Content);
        Debug.Log("Request Message: "+result.RequestMessage);
        Debug.Log("Version: "+result.Version);

    }
}

Whats causing the hanging issue??

Upvotes: 4

Views: 2176

Answers (2)

Scott Chamberlain
Scott Chamberlain

Reputation: 127543

Don't use HttpClient with unity, use the class WWW and unity's built in coroutine features, yield return it and it will wait for the download to complete.

public class HTTPManager : MonoBehaviour
{
    private IEnumerator Awake()
    {
        return ProcessRepositories();
    }

    private IEnumerator ProcessRepositories()
    {
        var form = new WWWForm();
        form.AddField("u", "test");
        var www = new WWW("http://localhost:8080/hello", form);
        yield return www;

        Debug.Log("responseHeaders: "+www.responseHeaders);
        Debug.Log("text: "+www.text);
    }
}

Upvotes: -2

JohanP
JohanP

Reputation: 5472

ProcessRepositories().Wait();

is blocking on async code and it is causing a deadlock. Stephen Clearly has a whole series of posts on this.

Either make all the code async all the way up or schedule continuations on your Task.

EDIT: It seems that Awake is a Unity method. For this you have 4 options:

1) Remove async Task from ProcessRepositories(). Remove the await in the method body and make your calls to your server synchronous. This will cause jitters and it not a recommended solution in a game environment.

2) Remove .Wait() from ProcessRepositories(). This will cause your code to async post to server but you won't be able to do anything with the the response. This is fine if you don't care about the response.

3.) If you do care about the response, you can schedule Continuations on ProcessRepositories(). This is a type of "callback" that will run when your Task has RanToCompletion or it errored out. To achieve this, change ProcessRepositories() to ProcessRepositories().ContinueWith(task=> { // in here you can access task.Result to get your response }) and change your ProcessRepositories method to return the HttpResponseMessage result i.e return await client.PostAsync("hello",content);

4) Use ConfigureAwait(false) as mentioned below but that will return the result on a different context and seeing that this Unity, you probably want the result on the UI thread, so just watch out for that.

Upvotes: 4

Related Questions