我将raspberry pi设置为服务器,通过HTTP将json作为输入。 " API"允许设置连接到pi的LED。一切正常,我可以从浏览器发送请求,一切都很棒。
响应到达需要一段时间。这就是我想要异步沟通的原因。
I found this on msdn that explains how it's done.
// Three things to note in the signature: // - The method has an async modifier. // - The return type is Task or Task<T>. (See "Return Types" section.) // Here, it is Task<int> because the return statement returns an integer. // - The method name ends in "Async." async Task<int> AccessTheWebAsync() { // You need to add a reference to System.Net.Http to declare client. HttpClient client = new HttpClient(); // GetStringAsync returns a Task<string>. That means that when you await the // task you'll get a string (urlContents). Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com"); // You can do work here that doesn't rely on the string from GetStringAsync. DoIndependentWork(); // The await operator suspends AccessTheWebAsync. // - AccessTheWebAsync can't continue until getStringTask is complete. // - Meanwhile, control returns to the caller of AccessTheWebAsync. // - Control resumes here when getStringTask is complete. // - The await operator then retrieves the string result from getStringTask. string urlContents = await getStringTask; // The return statement specifies an integer result. // Any methods that are awaiting AccessTheWebAsync retrieve the length value. return urlContents.Length; }
对于顶级概述,这里是我的Main方法的样子(它没有编译):
var pi1 = new RaspberryPi(@"http://192.168.0.100:8080"); // specify IP
var led = new Led(255, 100, 180); // r, g, b values wrapped in an Led object
Led result = await pi1.setLedAsync(2, led); // FAIL // what should be an async POST, awaiting the response
我希望这是有道理的。
Led
类只是一个数据对象,为3个通道保存3 byte
个s和json的一些转换方法。
setLedAsync
方法:
async public Task<Led> setLedAsync(uint n, Led led)
{
var client = new HttpClient();
client.BaseAddress = _uri;
var content = new StringContent(led.ToJson(), Encoding.UTF8, "application/json");
Task<HttpResponseMessage> response = client.PutAsync("/led/" + n, content);
HttpResponseMessage responseMessage = await response;
string json = await responseMessage.Content.ReadAsStringAsync();
return new Led(json);
}
这一行是使用await
时收到错误的地方:
Led result = await pi1.setLedAsync(2, led);
await
只能用于async
方法。
为什么会出现此错误?示例代码中的最后一个注释行
//等待AccessTheWebAsync的任何方法都会检索长度值。
让我觉得应该这样做。据我了解,await
基本上将Task<T>
解开为T
。
如果我不使用await
,我会收到类型错配,因为该方法返回Task<Led>
,而不是Led
。
让我感到困惑的是理解这个例子和我的情况之间的区别。我必须在await
方法中使用async
两次:
HttpResponseMessage responseMessage = await response;
string json = await responseMessage.Content.ReadAsStringAsync();
问题在于我必须以HttpResponseMessage
作为中间人。我怀疑我过早地放弃了第二次异步,等待某种方式(如果这有道理)我认为这是问题的根源,但我不知道如何解决它。
我将函数调用包装在一个asyn方法中,该方法允许编译代码。 但它不是异步的。我在服务器端添加了一个延迟来测试它。
class Program
{
static void Main(string[] args)
{
var prog = new Program();
Console.WriteLine("before init");
prog.init();
Console.WriteLine("after init"); // not happening before the response arrives
Console.Read();
}
private async void init()
{
var pi1 = new RaspberryPi(@"http://192.168.0.100:8080"); // specify IP
var led = new Led(255, 0, 0); // r, g, b values wrapped in an Led object
Console.WriteLine("before await");
Led result = await pi1.setLedAsync(2, led); // what should be an async POST, awaiting the response
Console.WriteLine("after await");
}
}
&#34;&#34;之后&#34;在请求的响应到来之前,消息将写入控制台。
答案 0 :(得分:8)
您收到错误,因为异步等待 - 等待 - 意味着执行等待的方法本身是异步的。我想你不明白等待意味着什么。等待不意味着同意阻止,直到结果可用 - 这就是相反的含义。等待意味着立即返回,以便我的呼叫者可以在不等待此结果的情况下完成重要工作;当结果可用时,在将来的某个时间安排此方法的其余部分。 Await是异步等待。当你等待信件到达邮件时,你不会坐在门边,什么都不做,直到它到来;你以异步方式完成其他工作,然后在信件到达后的某个时间恢复阅读邮件的任务。
你说方法 - 等待的方法,而不是等待返回任务的方法 - 是Main。如果这是一个控制台应用程序,那么你不能使Main异步,因为当Main返回程序结束时。再次,内化这个: await只是从当前方法的角度来看的回归。当前的方法将来会再次被称为 ,并将从中断的地方继续,但是当Main返回时,没有未来。所以你不能让Main async。
您注意到异步将T的任务转换为T,这是正确的,但它是异步。所以你在这里的主要选择是: