我的Unity游戏中有一个非常基本的脚本,它试图将POST中的表单数据提交给服务器。但团结似乎无限期地冻结/悬挂。我很困惑为什么会这样,所以我不知道如何解决这个问题。
我在本文后面松散地制作了我的代码: https://docs.microsoft.com/en-us/dotnet/csharp/tutorials/console-webapiclient#making-web-requests
我的服务器确实收到了请求并写回了一个。但是因为团结被冻结了,目前还没有真正可用。
我的班级看起来像这样:
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);
}
}
导致悬挂问题的原因是什么?
答案 0 :(得分:3)
ProcessRepositories().Wait();
阻止了async
代码并导致死锁。 Stephen Clearly在this上发布了一系列帖子。
将所有代码async
全部提升或安排Task
上的延续。
编辑:似乎Awake
是Unity
方法。为此,您有4个选项:
1)从async Task
移除ProcessRepositories()
。删除方法正文中的await
并使您对服务器的调用同步。这会导致抖动,而不是游戏环境中推荐的解决方案。
2)从.Wait()
移除ProcessRepositories()
。这将导致您的代码异步发布到服务器,但您将无法对响应执行任何操作。如果您不关心响应,这很好。
3。)如果你关心回复,可以在Continuations
上安排ProcessRepositories()
。这是一种“回调”,会在Task
有RanToCompletion
或出错时运行。要实现此目的,请将ProcessRepositories()
更改为ProcessRepositories().ContinueWith(task=>
{
// in here you can access task.Result to get your response
})
并更改ProcessRepositories
方法以返回HttpResponseMessage
result
即return await client.PostAsync("hello",content);
4)如下所述使用ConfigureAwait(false)
,但是会在不同的上下文中返回结果并看到这个Unity,你可能想要在UI线程上得到结果,所以请注意这一点。
答案 1 :(得分:0)
不要将HttpClient与团结一起使用,使用类WWW和内置协同程序功能的单元,返回它并等待下载完成。
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);
}
}