await immediately moves to next statement
Asked Answered
G

3

5

I am playing with the new Async CTP bits, and I can't get it work with either server-side or just command-line program (and all the examples are either WPF or Silverlight). For example, some trivial code like:

class Program {
    static void Main() {
        Program p = new Program();
        var s = p.Ten2SevenAsync();
        Console.WriteLine(s);
    }

    private async Task<int> Ten2SevenAsync() {
        await TaskEx.Delay(10000);
        return 7;
    }
}

returns immediately and prints System.Threading.Tasks.Task1[System.Int32]` instead of waiting for 10 secs and return 7 (as I would expect). Must be something obvious that I am missing.

Gainor answered 31/5, 2011 at 5:41 Comment(0)
F
11

The whole point of the await-based code is that it is indeed "execute the next stuff when this is finished" (a callback), and not "block the current thread until this has finished".

As such, from Ten2SevenAsync you get back a task, but that task is not yet complete. Writing the task to the console does not mean it waits for it to complete. If you want to block on the task's completion:

static void Main() {
    Program p = new Program();
    var s = p.Ten2SevenAsync();
    Console.WriteLine(s.Result);
}

or more explicitly:

static void Main() {
    Program p = new Program();
    var s = p.Ten2SevenAsync();
    s.Wait();
    Console.WriteLine(s.Result);
}
Flaming answered 31/5, 2011 at 5:59 Comment(4)
@Gainor - yes thanks, I am very familiar. And it works by exiting the actual method. If you exit Main (with only worker threads/tasks), you lose your process. It is not intended to act like synchronous code at all - it is just meant to be as convenient to write as synchronous code.Flaming
@Gainor - you only get an int if you await s. But if you await s you have exited Main() - boom; no more process. Emphasis: await s means "run this as a callback", not "block until this is complete". However, your code sample (question) does not show Main as an async method - so any async usage must be explicit. To be honest, it is a bad idea to make Main an async method anyway.Flaming
sorry; I misunderstood what you said... I removed my stupid comment, and marked this as an answer :)Gainor
Haha, the curse of the ambiguous keyword strikes again :)Lainelainey
U
2

I believe you just need to change the 4th line of your example to:

var s = await p.Ten2SevenAsync();
Ustkamenogorsk answered 31/5, 2011 at 5:43 Comment(4)
Worse! I added await and async to Main, and now it doesn't print anything at all. Feels like "await" immediately returns to the caller: with Task<int> from Ten2Seven, and with nothing (void) to OS.Gainor
If you make Main an async method, it will exit Main very early. And since the task happens on a worker, you will lose your entire process.Flaming
@MarcGravell can you explain above comment in more detail please??Condyloid
@Condyloid at the time of writing, static async Task Main() was not yet a thing; that comment refers to when the only option there was static async void Main() - and async void doesn't correctly convey completion status, causing the process to terminate too early; with async Task Main() it should be fine (this is why async Task Main() exists)Flaming
R
1

s is a reference to an asynchronous task. I haven't played with this myself yet so I'm not sure of the syntax, but there will be members of s that will allow you to check whether or not the task has completed, and then retrieve the result.

Reprieve answered 31/5, 2011 at 5:44 Comment(1)
You are correct; .IsCompleted and .Result (note .Result also includes an implicit .Wait())Flaming

© 2022 - 2024 — McMap. All rights reserved.