我正在尝试将代码从.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");
}
}
答案 0 :(得分:1)
一个解决方案是轮询完成,因为Nain提交了答案。如果您不想进行投票,可以使用TaskCompletionSource
。 This Q&A深入了解了原因和方法。
您的代码可以这样编写:
async Task CallerMethod()
{
JObject result = await GetToBackOffice(...);
// Do something with result
}
internal static Task<JObject> GetToBackOffice(string action)
{
var tsc = new TaskCompletionSource<JObject>();
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)
{
tsc.SetResult(Newtonsoft.Json.Linq.JObject.Parse(response.Data));
}
else
{
tsc.SetResult(null);
}
});
return tsc.Task;
}
另请参阅this msdn blogpost的异步方法调用协程并等待完成部分。
注意任务和async / await支持仅在Unity中以beta functionality的形式提供。另请参阅this帖子。
答案 1 :(得分:0)
写一个Co例程,如
//Class scope variable is neede to hold Resopnce other wise it will
//be destroied as soon as function is ended
ResponceType response;
IEnumerator WaitForResponce(ResponceType response)
{
this.response = response;
while(this.response.Data == null)
yield return new WaitForSeconds (0.02f);
//do what you want here
}
并致电合作例程
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);
StartCoroutine(WaitForResponce(responce));
}
else
{
idProcess = null;
}
});
答案 2 :(得分:0)
您需要提供回复&#34; return&#34;数据
internal static void GetToBackOffice(string action, Action<JObject>onCompletion)
{
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;
}
if (onCompletion){ onCompletion(idProcess);
});
}
方法返回boid,但如果需要,你可以返回HttpRequest。
请求的回调会将redult传递给onCompletion回调。
答案 3 :(得分:-1)
如果GetString方法返回一个Task对象,那么您可以使用Wait()方法让Task在返回结果之前完成处理。
var task = httpClient.GetString({
impl here..
});
task.Wait();
return idProcess;
&#13;