简体   繁体   中英

Async and await: multiple await expressions

I'm having a little difficulty understanding how use async and await work.

I understand that when an async method hits an await expression, the method returns immediately and at some point in the future the await expression returns and the method continues to execute.

What I don't understand, then, is what happens when an async method contains more than one await expression? When execution hits the second await expression, since the method has already returned after the first await expression was hit, what happens to execution around the second await expression?

I am currently reading two books on async and await but my dark mind has been illuminated by neither!

I understand that when an async method hits an await expression, the method returns immediately and at some point in the future the await expression returns and the method continues to execute.

Yes, if the awaitable hasn't already completed.

When execution hits the second await expression, since the method has already returned after the first await expression was hit, what happens to execution around the second await expression?

It returns control to whatever executed the continuation, which will depend on the context. In a WinForms app in the UI thread, it would just be the event loop. In a thread pool thread, it would just be the thread pool scheduler.

Chances are whatever calls the continuation really doesn't care about it at all - it's just "something to execute in a context". It's likely to go ahead and just execute whatever it needs to do next (or wait until there's more work).

The important point is that by now the first caller has the appropriate Task or Task<T> so that they can tell when the whole async method has completed.

It might help to recall that for each await the compiler encounters, it will rewrite the rest of the method as a continuation. So 2 awaits would result in 2 (nested) continuations, roughly equivalent (though overly simplified) to:

FirstAsyncThing().ContinueWith(x => {
    SecondAsyncThing().ContinueWith(y => {
        // etc.
    });
});

So just as the first await immediately returns control to the method's caller, the second returns control to first continuation 's caller, which is the first part of the original method.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM