【发布时间】:2018-01-19 21:35:46
【问题描述】:
我正在尝试将代码从 .Net 移植到 Unity C#,但我被困在包括回调在内的语法上。
基本上,我不得不将 .Net 'HttpClient' 库替换为 this one,也称为 'HttpClient'。但“Get”语法不一样,它使用回调。我对 C# 和 Http 查询很陌生,不知道如何处理这种语法以获得预期的回报。
.Net写的原函数:
internal static JObject GetToBackOffice(string action)
{
var url = backOfficeUrl;
url = url + action;
HttpClient httpClient = new HttpClient();
var response =
httpClient.GetAsync(url
).Result;
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
var idProcess = Newtonsoft.Json.Linq.JObject.Parse(response.Content.ReadAsStringAsync().Result);
return idProcess;
}
else
return null;
我为 Unity 编写的 C# 代码:
internal class Utils
{
internal static JObject GetToBackOffice(string action)
{
var url = backOfficeUrl;
url = url + action;
HttpClient httpClient = new HttpClient();
JObject idProcess = new JObject();
httpClient.GetString(new Uri(url),
(response) =>
{
// Raised when the download completes
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
idProcess = Newtonsoft.Json.Linq.JObject.Parse(response.Data);
}
else
{
idProcess = null;
}
});
// Here I would like to wait for the response, so that idProcess is filled with the received data before returning
return idProcess;
}
public class Action
{
public bool SendData(string id, string secretKey, FakeData data)
{
var idProcess = Utils.GetToBackOffice(String.Format("Events/{0}/infos",id));
//...I do then something with idProcess
//Currently, when I use idProcess here, it is still empty since the GetString response hasn't been received yet when this line is executed
return true;
}
}
public class EventHubSimulator : MonoBehaviour
{
void Start()
{
//Fill the parameters (I skip the details)
string oId = ...;
string secretKey = ...;
var vh = ...;
Action action = new Action();
action.SendData(oId, secretKey, vh);
}
}
我的问题是,在 GetToBackOffice 函数之后,我的代码直接将“idProcess”用于其他内容,但该对象为空,因为尚未收到响应。我想在我的函数返回之前等待响应。
我希望我已经足够清楚了。我知道已经发布了类似的问题,但找不到针对我的具体问题的解决方案。
编辑:
最后我按照 Nain 的建议使用了协程,但无法按照他所说的方式得到我所期望的。这种方式似乎可行(尽管这可能不是一个好方法)。
public class EventHubSimulator : MonoBehaviour
{
void Start()
{
//Fill the parameters (I skip the details)
string oId = ...;
string secretKey = ...;
var vh = ...;
Utils utils = new Utils();
StartCoroutine(utils.SendData(oId, secretKey, vh));
}
}
public class Utils: MonoBehaviour
{
private const string backOfficeUrl = "http://myurl/api/";
public CI.HttpClient.HttpResponseMessage<string> response;
public IEnumerator SendData(string id, string secretKey, FakeData data)
{
response = null;
yield return GetToBackOffice(String.Format("Events/{0}/infos", id)); //Make a Http Get request
//The next lines are executed once the response has been received
//Do something with response
Foo(response);
}
IEnumerator GetToBackOffice(string action)
{
var url = backOfficeUrl;
url = url + action;
//Make a Http Get request
HttpClient httpClient = new HttpClient();
httpClient.GetString(new Uri(url), (r) =>
{
// Raised when the download completes
if (r.StatusCode == System.Net.HttpStatusCode.OK)
{
//Once the response has been received, write it in the global variable
response = r;
Debug.Log("Response received : " + response);
}
else
{
Debug.Log("ERROR =============================================");
Debug.Log(r.ReasonPhrase);
throw new Exception(r.ReasonPhrase);
}
});
//Wait for the response to be received
yield return WaitForResponse();
Debug.Log("GetToBackOffice coroutine end ");
}
IEnumerator WaitForResponse()
{
Debug.Log("WaitForResponse Coroutine started");
//Wait for response to become be assigned
while (response == null)
{
yield return new WaitForSeconds(0.02f);
}
Debug.Log("WaitForResponse Coroutine ended");
}
}
【问题讨论】:
-
您能发布如何调用
GetToBackOffice()方法吗?是来自 Update() 还是其他地方? -
@S.Fragkos 从 Start() 调用
-
这会有所帮助吗:根据this 问题的公认答案,您可以定位.Net 4.5 并使用使用任务的“真实”HttpClient,而不是等待。
-
@PeterBons 实际上这是我尝试的第一件事。不幸的是,即使以 .Net 4.5 为目标,我也无法让 HttpClient 工作。它不是 c# 项目的引用,添加 dll 并没有解决问题。关于这个主题有this thread,所以 Unity 开发团队意识到了这个问题,但似乎没有人设法让它真正起作用。我想在花了两天时间尝试使它以这种方式工作后,我会尝试另一种方式。
-
好的,但是您可以在 .Net 4.5 的 Unity 中使用 async/await 不是吗?如果是这样,我可能有一个解决方案。