Asynchronous Programming in C# 5.0 part two: Whence await?


I want to start by being absolutely positively clear about two things, because our usability research has shown this to be confusing. Remember our little program from last time?

async void ArchiveDocuments(List<Url> urls)
{
  Task archive = null;
  for(int i = 0; i < urls.Count; ++i)
  {
    var document = await FetchAsync(urls[i]);
    if (archive != null)
      await archive;
    archive = ArchiveAsync(document);
  }
}

The two things are:

1) The “async” modifier on the method does not mean “this method is automatically scheduled to run on a worker thread asynchronously”. It means the opposite of that; it means “this method contains control flow that involves awaiting asynchronous operations and will therefore be rewritten by the compiler into continuation passing style to ensure that the asynchronous operations can resume this method at the right spot.” The whole point of async methods it that you stay on the current thread as much as possible. They’re like coroutines: async methods bring single-threaded cooperative multitasking to C#. (At a later date I’ll discuss the reasons behind requiring the async modifier rather than inferring it.)

2) The “await” operator used twice in that method does not mean “this method now blocks the current thread until the asynchronous operation returns”. That would be making the asynchronous operation back into a synchronous operation, which is precisely what we are attempting to avoid. Rather, it means the opposite of that; it means “if the task we are awaiting has not yet completed then sign up the rest of this method as the continuation of that task, and then return to your caller immediately; the task will invoke the continuation when it completes.

It is unfortunate that people’s intuition upon first exposure regarding what the “async” and “await” contextual keywords mean is frequently the opposite of their actual meanings. Many attempts to come up with better keywords failed to find anything better. If you have ideas for a keyword or combination of keywords that is short, snappy, and gets across the correct ideas, I am happy to hear them. Some ideas that we already had and rejected for various reasons were:

wait for FetchAsync(…)
yield with FetchAsync(…)
yield FetchAsync(…)
while away the time FetchAsync(…)
hearken unto FetchAsync(…)
for sooth Romeo wherefore art thou FetchAsync(…)

Moving on. We’ve got a lot of ground to cover. The next thing I want to talk about is “what exactly are those ‘thingies’ that I handwaved about last time?”

Last time I implied that the C# 5.0 expression

document = await FetchAsync(urls[i])

gets realized as:

state = State.AfterFetch;
fetchThingy = FetchAsync(urls[i]);
if (fetchThingy.SetContinuation(archiveDocuments))
  return;
AfterFetch: ;
document = fetchThingy.GetValue();

what’s the thingy?

In our model for asynchrony an asynchronous method typically returns a Task<T>; let’s assume for now that FetchAsync returns a Task<Document>. (Again, I’ll discuss the reasons behind this “Task-based Asynchrony Pattern” at a later date.) The actual code will be realized as:

fetchAwaiter = FetchAsync(urls[i]).GetAwaiter();
state = State.AfterFetch;
if (fetchAwaiter.BeginAwait(archiveDocuments))
  return;
AfterFetch: ;
document = fetchAwaiter.EndAwait();

The call to FetchAsync creates and returns a Task<Document> – that is, an object which represents a “hot” running task. Calling this method immediately returns a Task<Document> which is then somehow asynchronously fetches the desired document. Perhaps it runs on another thread, or perhaps it posts itself to some Windows message queue on this thread that some message loop is polling for information about work that needs to be done in idle time, or whatever. That’s its business. What we know is that we need something to happen when it completes. (Again, I’ll discuss single-threaded asynchrony at a later date.)

To make something happen when it completes, we ask the task for an Awaiter, which exposes two methods. BeginAwait signs up a continuation for this task; when the task completes, a miracle happens: somehow the continuation gets called. (Again, how exactly this is orchestrated is a subject for another day.) If BeginAwait returns true then the continuation will be called; if not, then that’s because the task has already completed and there is no need to use the continuation mechanism.

EndAwait extracts the result that was the result of the completed task.

We will provide implementations of BeginAwait and EndAwait on Task (for tasks that are logically void returning) and Task<T> (for tasks that return a value). But what about asynchronous methods that do not return a Task or Task<T> object? Here we’re going to use the same strategy we used for LINQ. In LINQ if you say

from c in customers where c.City == “London” blah blah blah

then that gets translated into

customers.Where(c=>c.City==”London”) …

and overload resolution tries to find the best possible Where method by checking to see if customers implements such a method, or, if not, by going to extension methods. The GetAwaiter / BeginAwait / EndAwait pattern will be the same; we’ll just do overload resolution on the transformed expression and see what it comes up with. If we need to go to extension methods, we will.

Finally: why “Task”?

The insight here is that asynchrony does not require parallelism, but parallelism does require asynchrony, and many of the tools useful for parallelism can be used just as easily for non-parallel asynchrony. There is no inherent parallelism in Task; that the Task Parallel Library uses a task-based pattern to represent units of pending work that can be parallelized does not require multithreading.

As I’ve pointed out a few times, from the point of view of the code that is waiting for a result it really doesn’t matter whether that result is being computed in idle time on this thread, in a worker thread in this process, in another process on this machine, on a storage device, or on a machine halfway around the world. What matters is that it’s going to take time to compute the result, and this CPU could be doing something else while it is waiting, if only we let it.

The Task class from the TPL already has a lot of investment in it; it’s got a cancellation mechanism and other useful features. Rather than invent some new thing, like some new “IFuture” type, we can just extend the existing task-based code to meet our asynchrony needs.

Next time: How to further compose asynchronous tasks.

Comments (161)

  1. J. Daniel Smith says:

    If I haven't gotten hopelessly confused, it would seem that the behavior of "await" has some similarities with "yield return".  If that's the case, perhaps revisiting various proposals involving "yield" would be appropriate.

  2. barrkel says:

    It amused me to no end to see that the switch from Begin/End async style (already almost perfect for manual CPS) to the new event-based async style (that made manual CPS very painful, and that I personally detested) has been reversed with much ugly code in the CTP, just to get back to something along the lines of Begin/End again. Take a look at how awkwardly the WebClient.DownloadStringTaskAsync extension method was implemented, compared to Stream.ReadAsync and Stream.WriteAsync.

  3. Michael Liu says:

    "yield for" has the right meaning, I think, although both words have a different sense here than the existing keywords.

  4. Stuart says:

    How about "after" instead of "await"? I'm still not sure I've wrapped my head precisely around the meaning of it all, but to the extent I *do* understand it, this syntax seems to express it:

    async void ArchiveDocuments(List<Url> urls)

    {

     Task archive = null;

     for(int i = 0; i < urls.Count; ++i)

     {

       after (var document = FetchAsync(urls[i])):

       after archive:

       archive = ArchiveAsync(document);

     }

    }

    I also changed the syntax to make the "after" statements look more label-y. I also removed the "if" statement, on the presumption that "after null:" would be a no-op.

    I think that it's clearer what this is saying – it's not saying "stop and wait for x" it's saying "here's what you should do after x is complete".

  5. Doni Grande says:

    What about ohwait, or the odata inspired owait…

    var MyData = ohwait GetMyData(….);

  6. holatom says:

    I'am very curious why yield AsyncFetch(…) was rejected for “await” syntax.

  7. StarBright says:

    I would vote for "continue with" as a contextual keyword to replace await.  It maps more directly to the underlying TPL implementation, has the advantage of working as a contextual keyword ("continue" is already a reserved word) and can be described as "continues execution of the method body with the result of the asynchronous operation when it is available"

  8. Ilia Jerebtsov says:

    I just watched the PDC demo, and the elegance of async methods completely blew me away. The way it's done feels to me as intuitive as it gets. It feels perfectly at home in C#, especially next to the way iterator blocks are done.

    I think what can be most difficult to grasp about asynchronicity is the actual implementation of an asynchronous method. The thought goes that there has to be somewhere, at some point, some method of "concurrency" that will actually execute the operation in parallel with your program's execution in order to allow the method to return instantly. Because from a programmer's perspective this is almost always achieved through some form of threading, it's easy to forget that it doesn't necessarily need to be that way.

    The callback could be triggered by, for example, a hardware interrupt. This in itself is asynchronously triggered by electricity coming down the wire, which was asynchronously triggered by someone pressing a button somewhere, because someone else asynchronously told them to. It's asynchronism all the way down, no threads involved.

  9. Stuart says:

    … or to combine my suggestion and StarBright's, how about "continue after"?

    async void ArchiveDocuments(List<Url> urls)

    {

     Task archive = null;

     for(int i = 0; i < urls.Count; ++i)

     {

       continue after (var document = FetchAsync(urls[i]));

       if (archive != null)

         continue after archive;

       archive = ArchiveAsync(document);

     }

    }

  10. louisila says:

    Looks like it should be AsynchAppend, which would show he control flow… which really is the purpose…Right?

    Your Description::“if the task we are awaiting has not yet completed then sign up the rest of this method as the continuation of that task, and then return to your caller immediately; the task will invoke the continuation when it completes.”

    so really what your doing is appending this method onto the previous task, asynchronously, which would lead me to believe that you should have the ability to do it in a blocking manor (the pair of which  may be useful in some situations)

    SO, I think AAppend or AsynchAppend, AppendA etc.. and the blocking counterpart BlockAppend.  

    unless the jiter can tell the difference from context..?, or we can attribute the method as [asynch]/[blocking], with asynch as the default…

    (I feel like a child on Santa's lap right now…)

  11. Dominik says:

    Your usability research is right. It is confusing. I find it very difficult to read your code snippet. To be honest it is not clear what's happening. I don't think the problem has to do with the naming of the keywords. It's too much magic going on. On the other hand i'm not the smartest person on the planet. But should i? I just want to read it…

  12. apaq11 says:

    How about 'await on' for the keyword? As in What's this line of code doing? It's awaiting on the Archive document.

  13. Stuart says:

    Or how about "yield until"?

    "yield until archive;"

    I still like "continue after" best, though.

    There's all sorts of ways you could go with syntaxes for the assigning version, too.

    "continue after AsyncFetch(…) into document;"

    "continue after document is AsyncFetch(…)"

    "continue after document from AsyncFetch(…)"

  14. J. Daniel Smith says:

    How about "yield continue"?  As with enumerators, yield says "I'm temporarily giving up control"; continue is already a keyword that happens to look similar to the behind-the-scenes mechanism.

  15. Frank Quednau says:

    Just so this voice is heard: async and await are fine to me. Of course not all subtleties of these new keywords have sunk in, but they will, and it seems to me "async" and "await" will feel quite natural after using them a bit. I don't see why "after", "continue", "…" should feel better.

    btw, yield is a tough word for non-native english speakers: When I look it up in the dictionary it has a gazillion meanings.

  16. Gabe says:

    I think that "resume after" better captures the intent than "await", although "yield until" has a nice ring to it.

  17. M.E. says:

    I also find it very difficult to read that code snippet. Let me see if I have this right:

    The function calls FetchAsync on each element of urls, and arranges for ArchiveAsync to be called on each result whenever that appears.

    No matter how many times I try to read the code snippet, I can't convince myself that that's what it says. I encourage you to take the feedback seriously: "await" sounds like it does the opposite of what it actually does. It's like when someone breaks up with you and says "See you around."

    I think you're having problems with people understanding "async" because the word "asynchronous" is unfortunate in the first place. It doesn't really mean what it sounds like, because "synchronous" in this context means not "at the same time" but "sequentially." So what we call "asynchronous" in CS should really have been called "non-sequential." Anyway, it's a highly technical meaning and it doesn't deserve to be used outside of CS papers.

    I realize you have probably spent many hours on this, so what do I know. But since Every Programmer Has An Opinion ™, here's my suggestion:

    someday void ArchiveDocuments(List<Url> urls) {

     Task archive = null;

      for(int i = 0; i < urls.Count; ++i)   {

       when(var document = FetchAsync(urls[i])) {

            when(archive == null)

                archive = ArchiveAsync(document);

       }

     }

    }

    Here, "someday" clearly indicates that the function is to schedule doing something eventually, rather than actually doing those things now, but does not have the same thread-related baggage as "async."

    The "when" block clearly indicates the contents of the continuation, and it does not suggest (which the await syntax does) that the contents of the block will be executed before the when clause finishes. It also resembles using blocks, because it's a block that sets up a context in which a given variable is defined. The only difference is that unlike a using, it does not block on the clause finishing, but continues the program, and executes the block whenever the clause is done.

  18. Jason says:

    This:    after (var document = FetchAsync(urls[i])):

    .. would make no sense. FetchAsync is returning a Task<T>. await is an operation on that task. It's not that we are waiting (sync or async) on the assignment to take place.

    I think the lexical syntax is completely understandable, however, 'yield', 'yield for', or 'yield until' may have made clearer syntax. I like to think of 'await' as meaning 'asynchronous wait'. It's the mathematical dual of 'yield'! (ok, maybe not)

  19. Stuart says:

    I agree with @M.E. that the "async" keyword could also be improved on, but it seems to me it rather depends on what you do with "await".

    "yielding" or "continuing" would be possible options, for example.

    I wonder whether you also considered requiring a keyword on calls to async methods even when they are not being immediately awaited?

    For example, ArchiveAsync returns void. So "archive = ArchiveAsync(document)" seems weird.

    How about "archive = begin ArchiveAsync(document);"?

    That way any call to an async method that *didn't* have either "begin" or "await" (or await's replacement) would be in error – I suspect that would avoid some misunderstandings or confusing code.

  20. Stuart says:

    @Jason: "FetchAsync is returning a Task<T>."

    I thought it was declared as returning "async Document"?

  21. Daniel says:

    I think 'async' and 'await' are fine. People are going to have to clear up their misconceptions about asynchronous programming and threads – it's not like Stream.BeginWrite/EndWrite were ever creating threads.

    That said, I do like the idea of using 'yield' in there, as that reminds me of cooperative multitasking. Maybe something like "yield wait"?

    @Stuart: you can't do that, there already are plenty of asynchronous methods in existing code. Remember that anything returning Task (or something else with a GetAwaiter() method) can be used with "await" – there's no need for an "async" modifier on the method, and callers of the method really shouldn't care how it was implemented – whether the compiler generated the task (using "async" keyword) or whether the programmer wrote the task-creating code manually (without using "async" keyword).

  22. LBushkin says:

    I doff my cap to the folks working on this model of async programming. I'm very impressed with how easy it is to interpret and understand this model and how well it composes with itself (which is typically one of the challenges of asynchronous development).

    Two things, however, I'm very curious to see are the debugging experience and the BCL enhancements relating to this model of asynchrony. Intuitive debugging in an async environment is hard to achieve – and with composable continuations, I suspect that we'll need some new debugging capabilities to make sure developers can wrap their heads around what is happening in the code … especially with the amount of sophisticated compiler magic involved.

  23. David says:

    I love "hearken unto". I think it fits great.

  24. Brian says:

    Why does Task<T> contain the method GetValue() when a property seems more appropriate? (Regardless of what it compiles to.) Or are there parameter versions of it as well?

  25. Jon Skeet says:

    I think the choice of keyword possibly depends on what point you're trying to get across: what happens at the *start* of the operation ("yield back to the caller") or what happens at the *end* of the operation ("continue with the rest of the program flow").

    One subtelty which hasn't been brought up – at least in the comments – is that it *might not* yield back to the caller. If the call to awaiter.BeginAwait() returns false (IIRC – maybe true; I haven't got the spec in front of me) then the method will continue *immediately*.

    Likewise although Eric mentioned continuing "on the same thread" that's only necessary for some synchronization contexts – such as ones in a UI. If you're writing server-side code and this is executing on a thread-pool thread, I believe the default synchronization context will allow it to continue on any random thread pool thread later.

    I think "async" is fine, but I think I'd like something involving "continue" where we've currently got "await". For example:

       var result = continue after DownloadStringTaskAsync(url);

  26. LBushkin says:

    With respect to BCL enhancements, I am curious how this asynchrony model will work with exist constructs such as BeginInvoke() / EndInvoke() on delegates. Those are already a common construct used to invoke operations asynchronously – however they return IAsyncResult – not Task<>. Will the compiler allow for transparent conversions between the two? Will there be new versions of these methods? Will developers have to explcitly use extension methods (or the like) to bridge the two? It would be a shame to not cleanly integrate with existing async constructs in .NET.

    I also think that it would be useful to add some syntactic sugar for expressing cancellation – rather than requiring developers to manually pass cancellation tokens everywhere. In my experience, you typically want *all* async operations started from some point to be cancellable – it's rarely necessary to be able to have fine grained control over which specific async steps should be cancelled (when you start more than one, that is). Since the compiler is already orchestrating the scheduling and execution of async operations, I think it makes sense to support abstracting away the concept of cancellation as well. I think an "ambient cancellation token" similar to how TransactionScope works for transactions would be helpful.

  27. Jason says:

    Declaring 'async Document' as the return type will compile as a method returning Task<Document>.

  28. Jason says:

    @Stuart, declaring 'async Document' as the return type will compile as a method returning Task<Document>.

  29. Matt Brunell says:

    I think that a new concept deserves a new keyword.  Granted, that technically, "async" is not currently a keyword, but I think that if it was used as shown, then a general misunderstanding would be present.  Putting something like "async" on a method declaration, at first inspection, I would think that it executes on a different thread.  

    Consider using a different word:  How about "deferred"?

    Not sure about "await"  I agree it feels somewhere between "yield" and "continue".  

    Just throwing things together:  How about "continue when"?

    deferred void ArchiveDocuments(List<Url> urls)

    {

     Task archive = null;

     for(int i = 0; i < urls.Count; ++i)

     {

       var document = continue when FetchAsync(urls[i]);

       if (archive != null)

         continue when archive;

       archive = ArchiveAsync(document);

     }

    }

  30. Juozas Kontvainis says:

    I suggest  using 'threaded' instead of 'async' and 'execute' instead of 'await'. It would not make code much more readable, but IMHO it also wouldn't make it less readable. However these words avoid the associations programmers already have with words 'async' and 'await' (the wait part in await :), probably making them more intuitive. Research of course is needed. Anyway, just a suggestion.

  31. David Nelson says:

    As usual, Jon Skeet has nailed it on the head. Some variation of 'continue' or 'yield' seems most appropriate ('yield until' definitely has the right ring to it).

  32. Jon Skeet says:

    @LBushkin: Yes, it shouldn't be a problem. You write a GetAwaiter() extension method for IAsyncResult, which returns something with BeginAwait(Action) and EndAwait().

    That's the beauty of it being a *pattern* rather than a specific type. The only ties to Task that I'm aware of are that an async method/anonymous function will always return a Task or Task<T>. I don't believe the way that that task is constructed is specified.

  33. Jason says:

    @Juozas, async doesn't imply threading. It could be async kernel IO, Windows messages, etc, that are providing the asynchrony.

  34. Jon Skeet says:

    @Juozas: Using "threaded" would *definitely* be the wrong word, IMO. It means there's a natural assumption that extra threads are involved, when they may well not be. For example, when you issue an asynchronous IO request, that doesn't require an extra thread to be running. You can have many, many asynchronous requests in flight at a time, using IO completion ports but not extra threads and the stack space hit incurred by those threads.

  35. Matt Brunell says:

    Does a simple 'defer' work?

       var document = defer FetchAsync(urls[i]);

    "defer" is sort like saying "I'll take care of this later"…

  36. LBushkin says:

    I haven't had a chance to play with the CTP yet, but it occurs to me that one construct that may be complicated by CPS-based asynchrony is using( ). How does something like this translate into a state machine:

       using( var conn = AcquireConnection() )

       {

            await SomeAsyncWork( conn );

       }

    What happens to deterministic disposal with exception occur, or cancellation is performed?

  37. John T says:

    I find myself turning the await statement into something like a using block which I find much clearer. I think the problem I have is not the keyword but seeing the different code blocks that will be executed. This seems much less upside down and inside out.

    async void ArchiveDocuments(List<Url> urls)

    {

     Task archive = null;

     for(int i = 0; i < urls.Count; ++i)

     {

       await (var document = FetchAsync(urls[i])

       {

           await(archive == null || archive)

           {

               archive = ArchiveAsync(document);

           }

        }

     }

    }

  38. Armen S says:

    async void ArchiveDocuments(List<Url> urls)

    {

     Task archive = null;

     for(int i = 0; i < urls.Count; ++i)

     {

       var document =  upon FetchAsync(urls[i]);

       if (archive != null)

         upon archive;

       archive = ArchiveAsync(document);

     }

    }

    Thoughts?

  39. Sandro Magi says:

    As others have noted, the connection with yield might be helpful, so how about: yield resume. This keyword combo this indicates that it behaves like enumerators by yielding immediately, and the "resume" implies a resumption from that point.

  40. Blake says:

    The obvious choice would be to split await between let!, do! & using!.

    Though, snark aside, it just struck me – I've not seen anything covering the "using!" scenarios yet.

  41. Rob says:

    "hearken unto" is definitely the best one so far. That would bring C# to the pinnacle of awesomeness.

  42. Data says:

    async is pretty fine – it's established in F# and rather convenient.

    @Blake let!, do! & using! are similar, but not the same – so it can be bewilder to those, who got used to the original )

    I agree with Jon Skeet – maybe there's should be smth with 'continue'…

    Hey, await isn't so bad thanks to its compactness. Continue…After… to long to such keyword

  43. Aaron G says:

    I want to put in my vote for the "continue after" syntax.  When I'm writing async code I tend to think of the control flow as a queue of operations (even though, strictly speaking, it's more like a pipeline).  The phrase "continue after" unambiguously says "schedule the rest of this stuff after X in the queue".

    It's far better than both "yield" and "await" in the sense that those two statements imply, well, *waiting*, which we might not actually be doing.  The phrase "continue after" doesn't, necessarily imply a wait; it should be intuitive that if the thing before us in the queue is already finished, then we're going to plow on ahead.

  44. Matthew Rodatus says:

    Cool stuff!! What about one of these?

    yield completed AsyncFetch(…)

    yield future AsyncFetch(…)

    future AsyncFetch(…)

    yield defer AsyncFetch(…)

    defer AsyncFetch(…)

  45. anon says:

    How about

    stop; FetchAsync(…) time;

  46. Joe says:

    How about:

       var document = GOSUB FetchAsync(urls[i]);

    Yeah, I have terrible ideas. I'll see myself out…

  47. Guy says:

    Eric, I have a bit of criticism.

    When you want to clarify a term you *_should not_* do it with a sentence as long and complex as:

    it means “this method contains control flow that involves awaiting asynchronous operations and will therefore be rewritten by the compiler into continuation passing style to ensure that the asynchronous operations can resume this method at the right spot.”

    Even at the cost of some accuracy. Prefer shorter bite size sentences. I am now much, much more confused than I was. Also you should not explain this from the POV of the compiler (which is what you are used to) but from the POV of a user. understanding how a feature is compiled *is not* Introductory by any means, again, even if it accurately depicts the behavior.

    I know explaining things you work with daily from start is difficult, I deal with that myself and make such errors all the time. This is why I wrote you this criticism.

    BTW, Thanks for the blog, read regularly.

  48. Aaron G says:

    It just occurred to me that this type of control flow is actually reminiscent of INTERCAL:

    en.wikipedia.org/…/COMEFROM

    Maybe instead of "await", the syntax should be "come from"!

  49. Ben says:

    I'm glad Eric posted on this today, my brain kept me up most of the night trying to work out whether await was short for async-wait, and how waiting could be synonymous with NOT waiting. That and pondering whether/why the async keyword was even necessary.

    Given that I'm not clear about the meaning/necessity of async, I can't really argue with it, but here are a few more suggestions to add to the list:

    yield while  (my favourite, and look!, no new keywords)

    pending

    on done resume next (wink at vb6)

    Shame we can't vote here.. if you feel strongly enough about it, try <a href="programmers.stackexchange.com/…/a>.

  50. Ben says:

    Just saw this question on Don Syme's blog, thought this might be a good place to ask it too:

    "Does this mean C# and VB will now also be relying upon tail call elimination in the VM?"

  51. John says:

    Eric, I hope you're still reading these comments. I'd like to suggest:

       var document = yield while FetchAsync(urls[i]);

    `yield while` perfectly captures the semantic meaning of the code — it yields while FetchAsync runs, and (just like the similar iterator construct) regains control once the value is processed. `yield until` would work also, but including the word `yield`, in my opinion, is a must — the similarity to iterators is too great not to use the same keyword for both. To quote John Leidegren from Stack Overflow, you are *yielding control*, rather than yielding values. (And to top it off, it reuses existing keywords)

    Just like in your usability tests, the `await` keyword was a major barrier to me understanding the concept. I'm very curious why `yield ____ task;` and its variants were rejected, if you'd be so kind as to respond with a sentence or two.

  52. Roland says:

    The "async" modifier confused me more than the await operator. Per your quote in the article:

    " They’re like coroutines: async methods bring single-threaded cooperative multitasking to C#."

    How about "comethod" instead of "async" for the modifier.

  53. Piki says:

    @John.

    "yield while" gets my vote.

  54. RuairiSpain says:

    I perfer to think of "await" as "when the tasks completes" so to me the keyword "when" makes more sense than await.  It's also one less letter to type!

    Task<string> data = DownloadAsync(url);

    string str = when data;

    How about renaming await to when?

  55. Blake says:

    @Data – you missed the snark, that wasn't a serious suggestion.   C# doesn't need the distinction between let! and do!, since expression values get silently discarded anyway.   Since the proposed await keyword forms an expression rather than a binding construct, in retrospect I presume it can just be used in:

    using (var foo = await Bar()) {…}

  56. Marcel Popescu says:

    I'll second the vote for "deferred" instead of "async". As for "await", "yield until" or (second choice) "yield while" seem better.

  57. Bryan Watts says:

    @John I was just about to offer the exact same suggestion. It captures the intent of the operation rather than its implementation.

    +1 yield while

  58. Sparkie says:

    Why not just make it "async DoWork(…)", since you're basically saying "do this work asynchronously"

  59. Harry Steinhilber says:

    I like 'continue after' or 'defer until' in place of 'await'. They give the needed feel that the program is going to go off and do something else and then come back here when this step completes. The jury is still out on async. I keep flip-flopping on whether it makes sense in my gut. Regardless of the symantics, though, a beautiful language feature to have.

  60. Richard Beauchamp says:

    +1 yield while

  61. Jesse says:

    I vote for "yield for" or "yield while".

  62. While we're throwing mad ideas around, how about "return until"? After all, that's precisely what it actually does in practice.

  63. Cory Nelson says:

    "yield until" gets my vote.  thank god some language finally got something like this — i think every serious async coder around has thought of this, but it's never been implemented until now because it requires too much language support.

  64. Pariuri Sportive says:

    Considerably, the article is in reality the greatest on this noteworthy topic. I agree with your conclusions and will eagerly look forward to your next updates. Saying thanks will not just be sufficient, for the wonderful clarity in your writing. I will immediately grab your rss feed to stay privy of any updates. Pleasant work and much success in your business dealings!

  65. Buryak Alexander says:

    "yield while/until" as well as "yield return" – is way to loooong to type it frequently.

    +1 for "await" – it's short and clear, ex:

    async void MegaBossAI() {

     while (IsAlive) {

       var player = FindClosestPlayer();

       await kill(player);  // short & human readable

       yield while kill(player);  // hm….

       yield until kill(player); // hm… 🙂

       return until kill(player); // return? return where? that player is not even killed yet!

       continue after kill(player); // nice, but even longer then YW

       await (kill(player)) { /* and what? place every routine into separate block, what for? */ }

       when kill(player); // looks like conditional op to me

       future kill(player); // mooom, not it the future, i want to kill him NOW!

       // other async stuff

     }

    }

  66. I'd pick 'task' as the keyword for the method modifier. That's what it makes.

    But 'await' is fine for the 2nd keyword. (Though I could live with 'hence'.)

  67. Jon Skeet says:

    Comments don't really let me go into enough details here, so I've blogged about it:

    msmvps.com/…/c-5-async-and-choosing-terminology-why-i-m-against-quot-yield-quot.aspx

  68. Jones says:

    Hi there, I am also completely confused by the await keyword. It feels like the code is lying, because "await" has the described "blocking, synchronous" feel to it. The yield option doesn't feel right either. What do you think of the following?

    async void ArchiveDocuments(List<Url> urls)

    {

     Task archive = null;

     for(int i = 0; i < urls.Count; ++i)

     {

       var document = will FetchAsync(urls[i]);

       if (archive != null) will archive;

       archive = ArchiveAsync(document);

     }

    }

    Making a literal transition of the snippet, I was trying to come up with some thing that would not have the same artificial feel of what is going on behind the scenes. The "await" keyword needs a lot of explanation, and so does every combination of yield.

    Ok, sure, my suggestion needs some explanation here, too:

    The simple WILL keyword is an indicator that there is something going on somewhere, but not right now. Synchronus code is more like: HEY, DO IT RIGHT NOW OR I, MYSELF WILL STOP DOING ANYTHING ELSE. Using "will" is more like a child saying to his parents: Yeah, I WILL clean up my room some time this week, but not right now, Pokemon is on.

    The parents are good with that, they want the room to be cleaned up by the end of the week. The care for the result asynchronously.

    Especially the part where it says: will FetchAsync this would work, but I myself am not to sure if "will archive" is the right style to use. Maybe renaming the variable could help, so something like:

      if (haveArchived != null) will haveArchived;

       haveArchived = ArchiveAsync(document);

    What do you think?

    bye, @cessor

  69. Armin Sander says:

    while "await" is a good choice, I would prefer "join" to make it clear that two paths of execution get together.

  70. Sinix says:

    Why not name the things as they behave?

    Actually, await dispatches the async operation with additional code to run as a task was accomplished. So, what about dispatch [with]/dispathches pair instead of await/async? Or "begin invoke with" – a slightly verbose, but a very recognizable pattern.

    If no, I still prefer something alike "continue" or "foo/bar" pair;)

  71. Filini says:

    +1 for "return until"

    I think "return" is totally the key point in this stuff, and marks the difference between "block until the async stuff completes" and "return to the caller, and resume the method after the async stuff completes".

  72. Blake says:

    Let's nip the "return until", or any other "return" variant in the bud, please.   This feature doesn't provide return semantics at all.  

    At the point marked by "await" (or some new keyword) the thread is potentially(*) released to execute other work, but flow of control NEVER returns to the caller from that point.

    (*) See Jon Skeet's blog entry linked above for the explanation about why it only potentially releases the thread.

  73. Filini says:

    @Blake: from Eric's post (bold text added)

    “if the task we are awaiting has not yet completed then sign up the rest of this method as the continuation of that task, and then RETURN TO YOUR CALLER immediately; the task will invoke the continuation when it completes.”

  74. ShuggyCoUk says:

    Oh and one more after a quick dictionary lookup.

    give way until

    Perhaps better for non English speakers? I still prefer "defer" though

  75. Blake says:

    @Filini – yes as far as it goes, but async methods are meant to be composed.

    Just as the async method you are writing uses "await" to call various async  methods in it's body, the caller will be using 'await' to call you.   This is the primary benefit, letting the whole call tree be structured in a simple, easy-to-reason-about fashion.    

    Only at the very bottom (where asyncs are being built out of platform primitives), and at the very top (where an entire async workflow is being kicked off with a TaskEx.Run or such) will this pattern not hold true.

  76. Jeroen Landheer says:

    I've been taking a look at several suggestions now, but I don't like "yield", I don't like "await" either. In some part Yield means litterally the opposite of "Await"; it describes the 'other' thing await does, while the truth is "You don't know what's going to happen". (Or you might know when you really analyze the whole thing through) 'defer' has this same problem.

    I suggested 'after' on John Skeet's blog, but come to think of it, a better suggestion might be 'future'. like it is going to be schedule somewhere in the future. It might be right now, it might be in a few seconds. It is certainly in the 'future' 🙂

    It even looks nice: var document = future FetchAsync(urls[i]);

  77. Hyacinth Broadchest says:

    I thought that the [Asynchronous] attribute meant "compiler, do not optimise this routine to share registers or any other clever stuff like that, because this routine is, well, asynchronous, and is liable to fire at any old time, so any path analysis that the optimiser might want to do will be misleading."

  78. leppie says:

    Personally (and subjectively), I kinda like the 'keyword' used in Scheme. It is called 'force'. I think F# uses 'do!' which I think is even better, but impossible for C#'s lexical syntax.

  79. Filini says:

    On the other hand… if we are "awaiting" in a loop, then "return" is even more misleading.

    Damn, choosing keywords is difficult 🙂

  80. Martin says:

    I like Stuart's keyword suggestion: use "after" instead of "await".  Almost impossible to misunderstand, even for non-native speakers.

  81. Eric M says:

    "upon"

    var document = upon FetchAsync(urls[i]);

  82. Eamon Nerbonne says:

    Great news, great features!

    My vote is to keep the keywords "async" and "await" as is.

    Of all the options proposed here, I find this combination best.  Yield is rather vague; already used by iterators, and sort of suggestive of the opposite data-flow.  Making "compiler magic" explicit by means of the async keyword is nice, particularly for maintenance programmers (a warning beacon advertising the special treatment the method is getting).

    Some people find it odd that await is particularly asynchronous (may return immediately) when it suggests synchronous waiting.  Well, an async method is really rather similar to a green thread; from the perspective of the thread of control which is the async method, await *is* essentially synchronous waiting.  The fact that it happens to be implemented by a compiler transformation rather than an OS thread is mostly an implementation detail (it can matter, but mostly in terms of synchronisation context).

    I also think the emphasis on the *differences* between OS threads and async methods is a little misplaced; they're easier to understand as threads that happen to be implemented differently.  Apart from places where the abstractions leak through (particularly, locking/synchronization), from a control flow perspective an async method is just a new thread that starts executing a method, synchronously waits when it hits "await", and communicates with its caller via Task.

    So: +1 for "async" and "await"!  They capture the most relevant part of the intuition (control flow) nicely.

  83. Michael McMullen says:

    First, I have no problem with async and can't think of anything that would feel better there to me.

    As for await, I was thinking about something like this:

    async void ArchiveDocuments(List<Url> urls)

    {

     Task archive = null;

     for(int i = 0; i < urls.Count; ++i)

     {

       continue after FetchAsync(urls[i])

         let document = value;

       if (archive != null)

         continue after archive;

       archive = ArchiveAsync(document);

     }

    }

    Although while writing this comment I've started to talk myself out of that, because it uses several existing keywords in similar but significantly different ways to how they are used now.  Maybe new keywords would be better than blurring the meaning of existing ones…

    async void ArchiveDocuments(List<Url> urls)

    {

     Task archive = null;

     for(int i = 0; i < urls.Count; ++i)

     {

       resume after FetchAsync(urls[i])

         with document = result;

       if (archive != null)

         resume after archive;

       archive = ArchiveAsync(document);

     }

    }

  84. pete.d says:

    Some thoughts:

    • Variations that include the word "continue" have the potential for being confused with loop continuations. I'm not sure "continue" is such a great option

    • I like "yield after", except that a) it's wordy, and b) unlike as the use in iterator methods, "yield" in this situation doesn't actually always yield

    • So, I'm left with the opinion that (as usual) the C# team has already done some great work, and found a pretty good word in "await" that does a reasonable job of describing what's going on from a high level point of view (I really liked Anders' explanation that other words confer the mechanism, while "await" confers the big picture)

    I think instead of worrying about the exact words to use (which it seems you've already spent a fair amount of time on and have come up with a good result), the effort should be in education. And in particular, I'd love to see more examples/details to explain why the "async" keyword is needed and how it works with the "await" keyword. The examples I see posted tend to combine the two in a single method, but from the other information I infer that they don't actually have to.

    That is, a method can be "async" without having an "await" (but if so, where does the Task<T> implementation come from?), while another method can have an "await" without being declared as "async". How do those scenarios play out (if they are indeed even valid…and if they are not, why not?).

  85. Sune Foldager says:

    The problem with most of the suggestions to replace 'async' is that, while async might not be optimal (although I like it), they are mostly even worse.

    For example, "defer" or "defered" seems to suggest that the execution of the method is defered; but this is clearly not the case. The method executes right away, but it might not finish right away. "threaded" is clearly bad, as it implies something which the model doesn't enforce. And "someday"… not even gonna comment on that ;-). But "async" is good because it says the following: Executing this method is not synchronuous, i.e. execution of your (calling) code is not gonna resume in sync with the method being done.

    Also, "await" is good if you think about it in terms of the flow of the code in the method, not the rest of the world. When "await" is encountered, the code does await the result before it moves on. It does not, true, sit in a loop and wait, or block the thread and wait. But it does wait in the sense that the code stops here. The whole point of this is to NOT think about the code as a continuation-riddled mess, but as a linear flow.

  86. Jon Skeet says:

    @pete.d: I don't believe that "await" without "async" is actually valid. From what I remember of what Anders said, "async" is really just to indicate to the compiler that it's an async method which might contain "await" – and to make it clearer to other human readers.

    An async method with no "await" will result in a compiler warning, but the task will be created in the same way as it would in the situation where every "await" actually completed synchronously. (I believe in the current implementation, the task to be returned is effectively created as soon as the async method is called.)

  87. MBR says:

    ++ for "continue with"

    await() has embedded "wait" which is the main source of confusion

  88. MBR says:

    >Damn, choosing keywords is difficult 🙂

    That's why this shouldn't be one at all…

  89. MBR says:

    >Damn, choosing keywords is difficult 🙂

    That's why this shouldn't be one at all…

  90. pete.d says:

    "I don't believe that "await" without "async" is actually valid."

    Interesting.

    You may be correct. I am still processing the information and don't yet have all my facts. 🙂 But, if it is true that "await" requires "async", then I find myself wondering why have "async" at all? Iterator methods do fine without a marker keyword to alert the compiler that the method is special; the compiler just uses the presence of "yield" in the method body.

    If "await" is present, why not just make "async" implied? And if "await" isn't present, what does "async" do on its own? Would it be possible to just not have "async" at all? Obviously a method with "await" would need an explicit Task<T> return type, but that seems fine to me. It's how iterator methods work anyway, and I'd find the consistency with that model desirable.

    What I don't find desirable is a syntactical requirement for me to specify something the compiler can easily figure out on its own. That seems like busy work for me the programmer, which I'd prefer to avoid. 🙂

    I am hopeful that at some point, Eric will have time to read through the barrage of comments we've added here and response with clarifications and additional details on topics such as these. I look forward to understand better why "async" was needed at all

  91. pete.d says:

    Oh, and another comment, related to some of the other suggestions:

    I definitely prefer the current linear model over a block-oriented approach suggested by some of the other commenters.  For me, the reason this adds value is that it offers a way to write and read the code that expresses the sequence of statements accurately but with a minimum of overhead.

    If a block-oriented syntax were desirable, it would be easy enough today to just write a library that uses methods accepting delegate references. We'd have no need for language support at all. It can be done as the language stands now, and would be just as awkward as incorporating a block-oriented approach into the language would be.

  92. pete.d says:

    (My apologies if this shows up twice…the blog said the message had been posted already, but the page was behaving a little oddly — the text of the comment didn't get cleared — and my comment never appeared. So I'm trying again, just in case).

    Hmmm…I'm just catching up on some of the other recent posts in this blog (I'm behind because of a MSDN/browser incompatibility issue that prevents me from seeing the articles in my usual browser). Last month, there was this article:

    blogs.msdn.com/…/ambiguous-optional-parentheses-part-three.aspx

    In it, Eric discusses how they might identify and deal with potential ambiguities introduced in new features.

    While I like the standalone "await" keyword, now I'm wondering if it doesn't introduce exactly the kind of ambiguity being discussed here. And if so, maybe that's why "async" was introduced as well (since it would remove the ambiguity)?

  93. Triger Konstantin says:

    My proposal is to make the keyword names express the programmer intention and not the underlined technical meaning. Therefore I would propose to remove the "async" keyword from the method signature (because I don't see the need in it neither from compiler nor from programmer perspective), instead I would use "async" in place of await to express that that method will be invoked asynchronously.

    In general this idea tries to align the feature usage with "yield" feature usage.

  94. pete.d says:

    "Therefore I would propose to remove the "async" keyword from the method signature (because I don't see the need in it neither from compiler nor from programmer perspective), instead I would use "async" in place of await to express that that method will be invoked asynchronously."

    As I've mentioned in my comments, I agree that I don't see the need for "async". But that may just be because there's a need I don't see, rather than there not being a need.

    More to the point here though, is that "async" isn't a suitable alternative to "await", for an important reason already stated previously: the invocation of the target of the special word ("await" or "async" or whatever) is not actually guaranteed to be executed asynchronously. The "async" keyword is definitely misleading in that context.

  95. fatcat1111 says:

    You are instructing the system to perform an action *when* something is done, therefore I think that "when" is the appropriate keyword.  

    var document = await FetchAsync(urls[i]);  

  96. fatcat1111 says:

    You are instructing the system to perform an action *when* something is done, therefore I think that "when" is the appropriate keyword.  

    var document = when FetchAsync(urls[i]);  

  97. Jones says:

    @fatcat1111

    I like your suggestion. It is simple and explicit.

    I would be fine with replacing the "await" with "async" and removing async from the method declaration aus pete suggested.

  98. pete.d says:

    As I mentioned, I think "await" is fine. But, having had more time to consider the question, and keeping in mind the desire for this to reflect the "what" rather than the "how", I think "await" and all the similar syntaxes aren't quite right.

    At the moment, my preferred syntax would be:

     • No "async" at all (i.e. method declaration is untouched…"async" is inferred from the body, like iterators)

     • The word "future" instead of "await"

    This is more declarative than imperative. That is, rather than telling the compiler "here's where we wait", you're telling the compiler that you want to assign the _future_ value of something. As in, "I know the value's not necessarily going to be available right this minute…I want whatever the value of it is in the future though".

    I saw another suggestion that argues in favor of no new keywords at all, and for the compiler to infer from usage what to do. That actually seems feasible to me — the plain vanilla scenario would be "assigning a Task<T> to a T would infer an 'await' [or 'future' or whatever it's called]" — but I'm sure I'm being naïve about it. 🙂

  99. wpuseuser says:

    Who doesn’t like to look sexy and be noticed for their superior flavor in style? Every female looks and feels sexy when she wears high heels. One man who helped to reinforce the trend of high heels is Christian Louboutin Pumps.

    One of his popular shoes is the Christian Louboutin Pumps Rolando. Christian Louboutin Pumps Rolando is found in different styles. The Christian Louboutin Pumps Rolando Hidden-Platform is an elegant chic shoe that can be damaged to correct dos. Christian Louboutin Pumps Rolando has a curved toe and a 5 shuffle heel. It is offered in sinister red and black patent leather. Christina Aguilera has been dappled tiresome the dark red patent leather Christian Louboutin Pumps Rolando on different occasions.

    Christian Louboutin Pumps are also untaken in a suede kill. The Christian Louboutin Pumps  hoary suede ‘Rolando’ platform pumps have has a refined, sophisticated air about it. It has a giving older suede greater, a trenchant toe and leather lining. It features a ¾” roofed front platform and a 4½” roofed heel. It is also offered in black.

    If you want a branded stylish piece of footwear that makes your legs look long and exquisite, get yourself a twosome of Christian Louboutin Pumps Rolando.

    http://www.christianlouboutinpumps.org

  100. Fabio Alves says:

    For me the best term is "watch" like in watchman or watchtower. For me the statement says "continue the code while I watch that variable here"

  101. diryboy says:

    Hi, please explain why need "async" modifier, because we don't need "iterator" modifier when using "yield return/break".

    Why not just generate Task when the method body has await expressions and returns Task/Task<T>/void?

  102. Beevik says:

    I like 'yield until', which someone proposed earlier in the comments.  'Yield' is nice because it captures the concept of yielding control to the calling function without implying blocking.  'Until' is nice too, because it focuses the reader's attention on the asynchronous method, not on the code beyond it.

    (I'm not a fan of 'continue' or 'after' in this context.  Continue is too reminiscent of the existing continue statement, and 'after' focuses your attention on the code that follows the asynchronous method.)

  103. Michael McMullen says:

    @Beevik: You don't like continue because of the existing continue statement, but you do like yield?  I don't see how either is better than the other in that regard.

  104. Julien Lebosquain says:

    I'm also in favor to remove 'async' completely to be coherent with how iterators work.

    As for 'await', as your usability search proved, it's quite confusing the first time. However, and it's the case for any new feature, once you got accustomed to it that's not really a problem anymore.

    That being said, I would prefer the keyword 'complete' instead of 'await' or any 'yield'/'continue' combination. We want that task completed, whether it already was or will be. I think the implied "wait if you have to" is quite clear with this word.

  105. Michael McMullen says:

    Just thought I'd remind people that Eric said in the original post "At a later date I’ll discuss the reasons behind requiring the async modifier rather than inferring it."

    May as well leave comments about removing that part entirely until that blog post…

  106. Sune Foldager says:

    @fatcat1111:

    Using "when" seems to indicate that only the next action is done when the result is available. Really, we need to think about this in terms of the flow of the code. In terms of that, the code DOES wait before moving on, as in: the next code is waiting for the result before it's executed. True, it's not busy-waiting or blocking the thread.

    But in terms of code-flow, it's certainly waiting.

    Also, to the people suggestions scoped await's: this breaks down a bit when you consider loops, where you actually jump back, to before the scope was created, but it's still part of the continuation.

    Again, think in terms of *flow of the code you're writing*, not so much in terms of the underlying threading model.

  107. Szindbad says:

    The biggest question remains for me is: throttling. How can i say that i want to download 10 archive in the same time from all the 100000 urls?

  108. Rick Sladkey says:

    Because of the close relationship between the async model and iterator blocks, the following exercise might be instructive.

    This code example uses async and await instead of yield return.  Provide an implementation of AsyncEnumerator<T>.

           public class EnumerableRange : IEnumerable<int>

           {

               int start;

               int end;

               public EnumerableRange(int start, int end)

               {

                   this.start = start;

                   this.end = end;

               }

               private async Task Enumerate(AsyncEnumerator<int> enumerator)

               {

                   for (int i = this.start; i < this.end; i++)

                   {

                       if (!await enumerator.YieldReturn(i))

                       {

                           break;

                       }

                   }

                   enumerator.Finished();

               }

               public IEnumerator<int> GetEnumerator()

               {

                   return new AsyncEnumerator<int>(Enumerate);

               }

               System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()

               {

                   return GetEnumerator();

               }

           }

  109. Marcel Popescu says:

    @Szindbad – there's an example in the 101 samples in the ctp download – look under Combinators

  110. Mike says:

    >> The “async” … “this method contains control flow that involves awaiting asynchronous operations and will therefore be rewritten by the compiler into continuation passing style to ensure that the asynchronous operations can resume this method at the right spot.”

    Why must I mark the method in this fashion? Can't the presence of the "await" keyword signal the necessary transformation in the same manner that the

    "yeld" keyword does today?

    As for "await", it reminds me of TSQL's WAITFOR except WAITFOR deals with time.

    -Mike

  111. Mike says:

    >> The “async” … “this method contains control flow that involves awaiting asynchronous operations and will therefore be rewritten by the compiler into continuation passing style to ensure that the asynchronous operations can resume this method at the right spot.”

    Why must I mark the method in this fashion? Can't the presence of the "await" keyword signal the necessary transformation in the same manner that the

    "yeld" keyword does today?

    As for "await", it reminds me of TSQL's WAITFOR except WAITFOR deals with time.

    -Mike

  112. Chris Taylor says:

    I have read the comments and thought I would throw in a list of alternatives that come to mind, though the more I think about it async/await seems just fine, the following options are floating around in the back of my mind.

    yield async

    yield while

  113. zzz says:

    C# v.N+1 parody

    [Verify=true]

    [NewOperatorsEx]

    [EnableParallel]

    public lazy async parallel excuse foo const int<A,B:{42}>(int x) : await all bases<A>(x){i}<~[bar]

    {

    return await volatile yield [€ > $ > §] (x=7?) { sporadic return $x?; } ;

    }

  114. zzz says:

    Let me get this straight. I need to type 6 extra characters "async " in every method just so some Fortune 5 company can get awayt without renaming their existing "await" lowercase things that don't conform to guidelines?

    If the async was a modifier that enabled a whole host of new operators and stuff in the future versions that broke all kinds of stuff to make nice things possible, it might be worth it. But you're selling it as enabling only the "await"?

    If the sole reason for adding this modifier is the risk of breaking existing code then can we have some proof that someone has publicly exposed API's with properties/interfaces that use lower case "await" in large code base? Lets give people a year to come up with their proof they're using it and if they don't then consider it as not in use.

  115. MH Lim says:

    Brilliant design and excellent choice of keyword!

    I like the fact that I code the method body sequentially. When the code reaches the await point, it waits. That’s what it does.

    I don’t need to know that the control will be transferred back to the caller, nor do I need to know how or when. That’s what async is for. Just stick the async keyword on the method header and let the compiler does its magic.

    Very nice separation of concern! So please keep both keywords.

  116. diryboy says:

    Hi, another try I did is async iterator, I wrote the following code but it won't compile…

    async Task<IEnumerable<int>> IteratorAsync()

    {

       for ( int i = 0; i < 10; i++ )

       {

           yield return await GetNum(i);

       }

    }

    private Task<int> GetNum( int i )

    {

       return TaskEx.Run(() => i);

    }

    I changed the return type of IteratorAsync() to IEnumerable<Task<int>>, and that won't compile, too.

    I just want to use some code like:

    foreach ( var item in await IteratorAsync() )

    {

       //..

    }

  117. MH Lim says:

    @diryboy

    I think there is an IAsyncEnumerable interface.

    Saw it here: blogs.msdn.com/…/a-technical-walk-through-all-of-the-async-ctp.aspx

  118. diryboy says:

    OK, I know why need "async" modifier, because async method body changes the "return". Iterators also changes "return", but it has a "yield" before it.

    In an async method that returns Task<T>, we actually write "return T" instead of "return Task<T>". And in the method body where it returns Task, no expressions should follow the return keyword (if there is).

    async static Task RunTask()

    {

       await TaskEx.Run(() =>

       {

           for ( int i = 0; i < 10; i++ )

           {

           }

       });

       return; // actually no need "return" here though.

    }

  119. Marcel Popescu says:

    By the way… nobody mentioned anything about CCR – msdn.microsoft.com/…/bb648753.aspx shows a method returning an IEnumerator of ITask and using the existing yield return instead of a new await keyword. The async / await combo *is* simpler, true, but the Ports in CCR were also a good idea.

  120. diryboy says:

    @MH Lim

    Thank you, I found this

    foreach (await var x in xx) Console.WriteLine(x);

    in the slide, but it doesn't compile..

  121. diryboy says:

    @MH Lim

    Thank you, I found this

    foreach (await var x in xx) Console.WriteLine(x);

    in the slide, but it doesn't compile..

  122. Pop.Catalin says:

    I think "yield while" or  "yield until" are the keywords that are the most appropriate to express the exact meaning of the intent, without suggesting any kind of  block operation.

    P.S. I would really like to replace "lock" with "synchronize" or "sync". I know it's impossible at this stage, but would be really helpful. It would avoid lots of missusages, by C# newcomers.

  123. kemsan says:

    async definitely the best keyword in front of the method declaration. I'd go with async for the method call too as in:

    var document = async FetchAsync(urls[i]);

  124. Paul says:

    I would vote for instead of "await" these ideas:

    "when"

    "proceed when"

    "until"

    "continue until" (favourite because it uses current meaning of "continue")

    "continue while"   (then we would have the negative logical statement)

    async void ArchiveDocuments(List<Url> urls)

    {

     Task archive = null;

     for(int i = 0; i < urls.Count; ++i)

     {

       var document = continue until FetchAsync(urls[i]);

       if (archive != null)

         continue until archive;

       archive = ArchiveAsync(document);

     }

    }

  125. William says:

    I'm not confident that I fully understand all the particulars of the new functionality, but what about "branch" for the keyword? It seems to me that the point here is to divide the control flow into two paths; the "main path" that we're enumerating ourselves and the "support path" that's handling some operation off in the background and will complete at an indeterminate point later. The "branch" might not last long– it might not happen at all, in fact, if the asynchronous operation completes immediately– but I think "branch" gets the point across that the we're splitting something off.

    But, as I said, I could be totally off the mark.

  126. Can says:

    I think async and await are fine. await is definitely better than anything that includes 'yield' in it. I understand the similarity of this construct to the IEnumerable yield but I don't think "yield" gives the semantics of what's going on.

    However, I'm looking forward to read the reasons behind requiring the async modifier rather than inferring it.

  127. Jeffrey L. Whitledge says:

    I would like to argue for the "await" keyword.

    If I understand correctly, some people object to "await" on the grounds that it isn't actually waiting, but is actually returning immediately to the caller. I don't think this is the correct way to look at it.

    Suppose two people go into a movie theater and decide to get some popcorn before watching the movie. If the line for the popcorn is short, then they will both stand in line and buy their popcorn, then go see the movie. If the line is long, then one will say to the other, "I'll await the popcorn. You go get us a couple of good seats, and I will join you in a few minutes."

    This is similar to what is going on here. The one who buys the popcorn (like the Async method) is going to wait for the task to complete in any case. The one who sometimes waits for the popcorn and sometimes goes straight to the seat (like the caller of the Async method) may or may not wait.

    In either case, at the location in the code in which the "await" keyword appears, waiting is going on.

    In the case where no waiting is necessary, because the called task has returned immediately (as in Jon Skeet's blog entry objecting to "yield"), then the await is analogous to a "foreach" called on an empty collection. In that case, there is simply nothing to await, so the method continues on.

    That's just my US$0.02.

  128. Stephen Cleary - Nito Programs says:

    I think that async/await is fine (possibly making the async keyword optional, since it's almost useless without await).

    However, I've never thought of "await" as just one word; in my head I've always translated it to "asynchronous wait", which is exactly what it is. (With the caveat that it may not *actually* be asynchronous – but this would likely be rare in practice).

    This opinion is coming from someone who's been doing async programming for >10 years, and is tremendously excited about this language change. 🙂

  129. zzz says:

    There's a video interview with the async team on Channel 9 where it was said they have a 2nd version of the compiler which doesn't need the async modifier. On another msdn blog there is a slide that says the async modifier is only needed for VB. From that you can draw your own conclusions why they chose to add it to C# anyway.

    From the suggestions so far, if C# has to have both then I'll settle for async + await, atleast they start with the same letter which makes them stand out.

  130. Aaron B says:

    i like async/async better than async/await.

  131. diryboy says:

    I think another reason "async" modifier should exist is that the Task of async method is kicked off when the method returns. Normal methods that return Task would not necessarily kick it off when the they return.

  132. Itai Frenkel says:

    WOW! Now all you need is to ask the Windows Azure team to guarantee the continuation is restored after machine fail-over.

    http://bit.ly/ae7Dih

  133. Brian Gideon says:

    The biggest compliant I have with the synax is that a keyword is embedded in an otherwise perfectly valid expression.  As a corollary to this it breaks away from the spirit of how iterator blocks were designed. For example, "return yield value" is not legal synax, but "yield return value" certainly is and fits the intuitive pattern of a keyword followed by a continuation statement.  Modelling the syntax of this new feature after the iterator syntax we might be better served with the following syntax.

    async void ArchiveDocuments(List<Url> urls)

    {

       Task archive = null;

       foreach (Url item in urls)

       {

           Document document;

           await FetchAsync(item) capture document;

           if (archive != null) await archive;

           archive = ArchiveAsync(document);

       }

    }

    Notice that I precede the continuation statement with the `await` keyword and use a new keyword 'capture' to capture the return value into a local variable.  I am envisioning several different variations for capturing that return value, but the point I want to drive home is that the keyword that gets everything "going" precedes the statements it acts upon instead of getting embedded in it.

    Also, I vote to abolish the 'async' keyword if it is deemed sufficient that it could be inferred by the compiler. I am, of course, prepared to retract my vote if there is some complusory reason for its existence.

  134. Richard Hein says:

    How about callback for the keyword?

  135. David McKenzie says:

    Why do keywords need to be actual English words? In this instance, that seems to be causing some problems, because most of the candidates have meanings or associations in regular usage that are irrelvant or misleading.

    Suggestion: use "cwith" instead of "await". It is pronounceable and reasonably memorable, short and easy to type, and relatively free of stray associations. (I created it by contracting "continue with", which is my favorite of the suggestions so far.)

    If you don't like that one, try other neologisms / contractions / invented words.

  136. Alex Simkin says:

    What about symbol instead of 'await'. Something like <> or ><.

    var document = <> FetchAsync(<> GetIdAsync());

  137. Tom says:

    I think 'async' and 'await' are perfect.  They're short and simple, they comprise only one keyword apiece (two for the entire feature set), and they both start with 'a', which implies they work together.  'yield for' takes two completely unrelated keywords and implements them in a non-intuitive way for which neither was intended; 'continue' is already used in a synchronous context and should not be re-used for something quite the opposite.  'after' doesn't even make since to me; you're not executing the method "after" anything, you're calling it immediately and then doing other stuff while you wait for it to finish executing.  I say stick with the a's.

  138. Gilles says:

    Read most but not all comments. One of the first thing that occurred to me was "yield pending". Apologies if it's already been put out there.

  139. Mark Knell says:

    Typo in "which is then somehow asynchronously fetches": spurious "is".

    Awaiter, there's a bug in my spaghetti code.

  140. Jordão says:

    (Too many comment here, so I didn't read them all, my suggestion might have already been given.)

    Why not, instead of "await", just use …. "async" again ?

  141. Jordão says:

    (Too many comment here, so I didn't read them all, my suggestion might have been already been given.)

    Why not, instead of "await", just use …. "async" again ?

  142. John Fisher says:

    Since the function is being modified to return a task, why not use "task" as the keyword?

    "finish" would work well instead of "await", since you need the function to be completed, but you don't necessarily need to wait.

  143. Pete Montgomery says:

    Eric! How about "await return". It makes it clearer that the method returns here, and mirrors "yield return" exactly.

    Cheers,

    Pete

  144. Chris Rogers says:

    I think "continue" or "continue after" or "yield" are far, far, far better choices than "await".

    "await" simply reeks of blocking and I would be fascinated to understand why the other choices were all discarded.

  145. Neal Tibrewala says:

    I very much like "yield until".  Await feels like a blocking call.

    yield, tell me that control flow is returning to the caller, just like in an iterator block, and 'until' is telling me when control is returning to this block again "go away until this thing is done".

  146. Michael Litwak says:

    "It is unfortunate that people’s intuition upon first exposure regarding what the “async” and “await” contextual keywords mean is frequently the opposite of their actual meanings"

    There's nothing wrong with people's intuition or ability to understand terms in context.  If the keyword is ambiguous to many people, it is a poorly chosen keyword.  If the keyword's meaning seems to be the opposite of what it is, then there couldn't be a WORSE choice for the keyword.

    If I understand correctly, the await keyword does two things in a particular sequence: it starts the code that follows in an async task and THEN returns to the calling method immediately.  This is a fairly complex action that warrants a descriptive keyword.

    I suggest using the keyword ReturnAfterStarting rather than await.  Sure it is long, but so what?  We've got hundred gigabyte hard disks, compilers and IntelliSense; we can deal with a few more bytes in the source for the sake of clarity.  Let's do away with keywords that can be understood only after you've scratched your head for hours and done multiple trial-and-error tests.

    My first thought was ReturnFire, but may be too steeped in English idioms to be suitable.

  147. George Panayotopoulos says:

    I agree with all those that were confused with the the name used for this  new  "await" operator. Plato has said that we are at the beginning of wisdom when we start visiting and exploring the names.

    So my proposal is to use the word "anathesis" [of greek origin] which means "assign a job and return".

    The fact that is not well known to English speaking people is good because they will oblige most of the readers to look for its meaning and as a result they will not be confused by the preconceptions they already have. On the other hand, the "anathesis" operator  will pair perfectly with the "async" keyword which is also of greek origin.

  148. Eber Irigoyen says:

    var document = continuation FetchAsync(urls[i]);

  149. Andrey says:

    Why two different word – await and async. Couldn't people just get by with one – async – for both methods and calls? BTW, async in calls in by fa the least confusing (compared to await at least 🙂

  150. Damon Sutherland says:

    After reading through a number of these comments, I tend to agree with StarBright and Jon Skeet for the "await" keyword.  I personally prefer "continue with" (StarBright's reasoning makes a ton of sense to me), but I could live with "continue after".

    As for the "async" keyword, it really does seem counter intuitive, but I like Roland's idea of "comethod", or perhaps "coop".

  151. Keith Hill says:

    I'm fine with "await".  As alpha coders I believe we tend to think too much about the "how" (and in excruciating detail).  If you look at these async methods, they're kind of like work flows that operate over discontiguous chunks of time and possibly threads.  So if my workflow says that a result is awaiting the completion of a certain async operation that make sense to me.  

    If you want to get pedantic about keywords reflecting reality, then seems like there should be an uproar over the use of "return" in one of the new async methods.  After all, the method will typically return well before it hits the "return" statement.  But again, from a workflow point of value, that makes sense to me because it is returning the final result from the workflow.

    Now I'm not so sure about the need for "async" but if a modifier is absolutely needed, then I prefer "async".

  152. Joshua A. Schaeffer says:

    BTW "await" doesn't just yield the thread timeslice, it yields the thread itself!  So "yield *" in its place would definitely make sense.

    My vote would be for "yield while" or "yield until" except when you consider that this new thread-agnostic method is destined to become the way all .NET asynchronous code is written… you would tire of writing that when a short "await" could be used in place.

  153. hemp says:

    'eventually' – following the statement to yield with.

    var document = FetchAsync(urls[i]) eventually;

    if (archive != null)

       archive eventually;

    Alternatively, 'eventually then'

    var document = FetchAsync(urls[i]) eventually then;

    if (archive != null)

       archive eventually then;

    archive = ArchiveAsync(document);

  154. dmihailescu says:

    Eric,

    Here are my 2 cents at the first view of these new concepts

    replace async with 'blocked' and await with 'deferred'

    your code becomes:

    blocked  void ArchiveDocuments(List<Url> urls)

    {

     Task archive = null;

     for(int i = 0; i < urls.Count; ++i)

     {

       var document = deferred  FetchAsync(urls[i]);

       if (archive != null)

         deferred archive;

       archive = ArchiveAsync(document);

     }

    }

    the intent is decribed better in my opinion

    another good choice would be  async  -> 'finalized' and await -> 'nonfinalized'

  155. Michael says:

    This is a commendable feature but I know developers will abuse it. They will call "async" functions treating them like synchronous function and they will then start seeing horrible race conditions and deadlocks. The confusion that you fight against at the beginning of this post won't just go away.  Think very carefully before you release this feature.

  156. Dr. Venkman says:

    Instead of 'wait' it should say 'resumable'…

  157. Mark says:

    How about the using the keyword "start"?

  158. CL says:

    I would like to replace 'await' with 'async'. Then replace 'async' with 'task' or something else.

  159. Guy Murphy says:

    I would have liked to see the keyword "defer" used in place of "await".

  160. Hans-Rudolf Thomann says:

    My proposal: "afterwards" and  simplify the syntax as follows:

    async void ArchiveDocuments(List<Url> urls)

    {

    Task archive = null;

    for(int i = 0; i < urls.Count; ++i)

    {

      var document = FetchAsync(urls[i]):

      afterftwerards archive:

      aftgerwards archive = ArchiveAsync(document);

    }

    }

    Do you like it?

  161. Dave says:

    Nevermind, it just seems Part Two has a different title that the other parts…