Situation
I have a raspberry pi set up as a server taking json via HTTP as input. The "API" allows to set leds connected to the pi. That all works, I can send requests from the browser and everything is great.
It takes a while for the response to arrive. That's why I want to communicate asynchrounously.
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; }
For the top level overview, here's how my Main method looks like (it doesn't compile):
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
I hope that makes sense.
The Led class is just a data object holding 3 bytes for the 3 channels and some conversion methods to and from json.
The setLedAsync method:
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);
}
Error
This line is where I get an error for using await:
Led result = await pi1.setLedAsync(2, led);
await can only be used in an async method.
Questions
- Why do I get this error? The last comment line in the example code - // Any methods that are awaiting AccessTheWebAsync retrieve the length value. - makes me think that this is how it should be done. As I understand it, the - awaitbasically unwrapps the- Task<T>into a- T.- If I do not use - await, I get a type missmatch, because the method returns- Task<Led>, not- Led.
- What's confusing for me is to understand the difference between the example and my situation. I have to use - awaittwice in my- asyncmethod:- HttpResponseMessage responseMessage = await response;
- string json = await responseMessage.Content.ReadAsStringAsync();
 - The thing is that I have to deal with this - HttpResponseMessageas a middleman. I suspect that I'm prematurely giving up the asynchronousity with this second await somehow (if that makes any sense) I think this is the origin of the problem, but I'm not sure how to solve it.
Edit
I wrapped the function call in an asyn method, which allows to compile the code. But it's not asynchronous. I added a delay on the server side to test this.
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");
    }
}
None of the "after" messages are written to the console before the response from the request arrives.
 
    