Now that we know what is in store for c#5, there is apparently still an opening for us to influence the choice of the two new keywords for 'Asynchrony' that were announced by Anders Heijsberg yesterday at PDC10.

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);

Eric Lippert has an explanation of the choice of the current two keywords, and the way in which they have been misunderstood in usability studies. The comments have several other propositions.

Please - one suggestion per answer, duplicates will be nuked.

  • By the way "language-integrated asynchronous programming" gives us LIAP, doesn't quite roll off the tongue the same way as LINQ ;)
    – Benjol
    Commented Oct 29, 2010 at 20:51
  • 1
    Unless its pronounced leap. Commented Oct 29, 2010 at 21:17
  • 4
    But "Language-Integrated Asynchronous Runtime" acronyms up nicely.
    – glenatron
    Commented Oct 29, 2010 at 22:06
  • This has got to be off-topic.
    – DeadMG
    Commented Jan 24, 2012 at 4:45

12 Answers 12


Given that I'm not clear about the meaning/necessity of async, I can't really argue with it, but my best suggestion for replacing await is:

yield while (look! no new keywords)

Note having thought about this a bit more, I wonder whether re-using while in this way is a good idea - the natural tendency would be to expect a boolean afterwards.

(Thinks: finding good keywords is like finding good domain names :)

  • +1 and by the way, you beat me to commenting on his blog entry by 7 minutes... Commented Oct 29, 2010 at 21:01
  • But you're not necessarily yielding execution if the task has already been completed. But you're always awaiting the completion of the task (though never waiting). Commented Oct 29, 2010 at 23:43
  • @Allon You don't necessarily run the loop body of while(x) {...} either, if x is false. Commented Oct 30, 2010 at 1:09
  • @Note: Well there's no verb in while. If you do add a verb, like do, then you get do {...} while (x), which does executes the body regardless of x (at least once). Your suggestion of yield while seems very similar to do while, but with opposite guarantees of performing the verb, which might be a bit misleading (but not that much of a big deal). The thing I dislike the most about yield is that it implies the implementation of a mechanism. The whole point of async/await is that you write a asynchronous operation in a synchronous style. yield breaks that synchronous style. Commented Oct 30, 2010 at 9:41
  • 1
    I don't think this clears up any of the confusion that Eric Lippert described. It actually appears to be a victim of that confusion. Commented Nov 5, 2010 at 19:07

How about not having a keyword?

I'd like the compiler to realise that, most of the time, when I call an asynchronous method, I want the result of it.

Document doc = DownloadDocumentAsync();

That's it. The reason people are having a hard time thinking up a keyword for this thing is because it's like having a keyword for "do the thing you'd do if things were perfectly normal". That should be the default, not require a keyword.


I originally suggested the compiler should get clever with type inference to figure out what to do. Thinking further about this, I'd keep the existing implementation in the CTP as it is, but make a couple of trivial additions to it, so as to reduce the cases where you'd need to use the await keyword explicitly.

We invent an attribute: [AutoAwait]. This can only be applied to methods. One way to get this applied to your method is to mark it async. But you could also do it by hand, e.g.:

public Task<Document> DownloadDocumentAsync()

Then inside any async method, the compiler will assume you want to await on a call to DownloadDocumentAsync, so you don't need to specify it. Any call to that method will automatically await it.

Document doc = DownloadDocumentAsync();

Now, if you want to "get clever" and obtain the Task<Document>, you use an operator start, which can only appear before a method call:

Task<Document> task = start DownloadDocumentAsync();

Neat, I think. Now a plain method call means what it usually means: wait for the method to complete. And start indicates something different: don't wait.

For code that appears outside of an async method, the only way you're allowed to call an [AutoAwait] method is by prefixing it with start. This forces you to write code that has the same meaning regardless of whether it appears in an async method or not.

Then I start to get greedy! :)

Firstly, I want async to apply to interface methods:

interface IThing
    async int GetCount();

It basically means that the implementing method must return Task<int> or something compatible with await, and callers to the method will get [AutoAwait] behaviour.

Also when I implement the above method, I want to be able to write:

async int GetCount()

So I don't have to mention Task<int> as the return type.

Also, I want async to apply to delegate types (which, after all, are like interfaces with one method). So:

public async delegate TResult AsyncFunc<TResult>();

An async delegate has - you guessed it - [AutoAwait] behaviour. From an async method you can call it and it will automatically be awaited (unless you choose to just start it). And so if you say:

AsyncFunc<Document> getDoc = DownloadDocumentAsync;

That just works. It's not a method call. No task has been started yet - an async delegate is not a task. It's a factory for making tasks. You can say:

Document doc = getDoc();

And that will start a task and wait for it to finish and give you the result. Or you can say:

Task<Document> t = start getDoc();

So one place in this where the "plumbing" leaks out is that if you want to make a delegate to an async method, you have to know to use an async delegate type. So instead of Func you must say AsyncFunc, and so on. Though one day that kind of thing might be fixed by improved type inference.

Another question is what should happen if you say start on an ordinary (non-async) method. Obviously a compile error would be the safe option. But there are other possibilities.

  • This might be doable with an implicit conversion but otherwise would require left-to-right evaluation of the statement (which is exactly the opposite of how the compiler normally works, except for lambdas). I think I'd still be against this because it prevents the use of var, potentially having to substitute some long explicit type name, and is also ambiguous between the await case and the case where somebody accidentally called the async method instead of the normal synchronous method. It seems intuitive at first but actually violates the principle of least surprise.
    – Aaronaught
    Commented Nov 1, 2010 at 18:45
  • @Aaronaught - Why does it prevent the use of var? I wonder if you're responding to the previous revision of my answer... I've completely rewritten it. You can now think of this suggestion as follows: if the method is marked with a special attribute, it's as if the await keyword is automatically inserted in front of calls to that method (unless you suppress this with the start prefix). Everything stays exactly as in the CTP, and hence var works fine. Commented Nov 1, 2010 at 18:53
  • Indeed I was... strange that I decided to revisit this thread and respond to your answer at almost exactly the same time that you decided to edit it. I'll have to reread it now...
    – Aaronaught
    Commented Nov 1, 2010 at 19:21
  • 1
    I like your inversion of the await keyword. And I also dislike the triple-redundancy of public async Task<int> FooAsync(). Commented Nov 1, 2010 at 19:50
  • 1
    Yes, I see that Async-postfix naming convention as a sign that something could be captured more formally. Basically, if there's a rule saying "methods like this should be named a certain way, so people know how to call them properly" then it follows that the same rule could be used to attribute those methods a certain way, and then the compiler to help you to call them properly. Commented Nov 2, 2010 at 12:28

I think async is fine, but maybe that's because I associate it with ASP.NET async pages - same idea.

For the await keyword I prefer continue after or resume after.

I don't like yield or any of its variants, because the semantics are such that the method may never actually yield execution; it depends on the state of the task.

  • I like resume after for await. Maybe async could be called resumable. Commented Nov 5, 2010 at 20:37
  • Although I'd prefer just after, the continue after approach has a strong implementation advantage: it includes a currently existing contextual keyword, but with a syntax that is not compatible with the current usage. That guarantees that the addition will never break existing code. When using an entirely new keyword, the implementation needs to cope with possible uses of the word as an identifier on older code, which can get quite tricky. Commented Mar 31, 2011 at 13:59

I added to comments on Eric's blog too, I don't see any issues with using the same keyword async

var data = async DownloadFileAsync(url);

I'm just expressing that I want to download the file asynchronously. There's a bit of redundency here, "async" appears twice, because it's in the method name too. The compiler could be extra clever and detect the convention that methods ending in "Async" are infact async methods, and add that for us in the compiled code. So instead you might just wanna call

var data = async DownloadFile(url);

as opposed to calling the synchronous one

var data = DownloadFile(url);

Heck, we should also be able to define them the same way, since the async keyword is there in our declaration, why must we manually add "Async" to each method name - the compiler can do it for us.

  • I like the sugar you added, although the C# guys probably won't go for it. (FWIW, they already do something similar when searching for attribute names) Commented Oct 30, 2010 at 1:14
  • 2
    And given that the async keyword on the method is just a nicety (if I've correctly understood), I wonder whether the best thing wouldn't be to do the opposite of what you suggest: abandon the async on the method, and just use it where they currently have await.
    – Benjol
    Commented Oct 30, 2010 at 15:45
  • That's a possiblity. The async keyword on the method delcaration is just there for cleanliness really. I would prefer it kept there, but without the requirement for us to add "Async" to method names. Eg async Task<Byte[]> DownloadFile(...) rather than Task<Byte[]> DownloadFileAsync(...) (The latter will be the compiled signature anyway). Either way works.
    – Mark H
    Commented Oct 30, 2010 at 17:51
  • I'm honestly not a fan of this either. As in a previous comment I have to point out that your final version violates the principle of least surprise, as it is actually invoking a completely different method from the one written, and the implementation and signature of that method is entirely up to the implementing class. Even the first version is problematic because it's not really saying anything (asynchronously execute this asynchronous method?). The thought we're trying to express is a continuation or deferred execution and this doesn't express that at all.
    – Aaronaught
    Commented Nov 1, 2010 at 18:48

async = task -- It's modifying a function to return a task, so why not use the keyword "task"?

await = finish -- We don't necessarily need to wait, but the task has to "finish" before using the result.

  • It's really hard to argue with the simplicity here.
    – sblom
    Commented Jan 24, 2012 at 4:05

I like yield until. yield while, already suggested, is great and doesn't introduce any new keywords, but I think "until" captures the behavior a little better.

I think yield <something> is a great idea, because yield already captures the idea of making the rest of the method a continuation so well. Maybe someone can think of a better word than "until."


I just want to register my vote for Aaron G's suggestion of comefrom -- the first appropriate use I've seen of INTERCAL's COMEFROM statement. The idea is that it's sort of the opposite of GOTO (jumping away from the GOTO statement) in that it makes some place in your code jump to the COMEFROM statement.


Since we are dealing with Task<T>s, how about using start as a keyword preceding the statement, as in:

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

  • Hmmm, perhaps finish would be even better than start? Commented Nov 6, 2010 at 10:19

It's worth noting that F# also uses the async keyword in its async workflows, which is pretty much the exact same thing as the new async functionality in C#5. Therefore, I'd keep that one the same

For the await keyword in F#, they just use let! instead of let. C# doesn't have the same assignment syntax, so they need something on the right side of the = sign. As Benjol said, it functions the same as yield so it should almost be a variant of that.

  • 2
    An "await" need not be in an assignment at all (though of course typically it is.) It is legal as an operator on pretty much any expression that has a type we can find a GetAwaiter on. (The exact rules are yet to be worked into a publishable form.) Commented Oct 30, 2010 at 0:05
  • 1
    @Eric, in F# that would be do!, but you knew that...
    – Benjol
    Commented Oct 30, 2010 at 15:41

yield async FetchAsync(..)

This goes perfectly with the async modifier you need to put on the method you're invoking. And also the semantic of the current yield return that is, you return and yields execution to the enumerating code while in this case you're yielding your execution to the asynchronous method.

Imagine if in the future there'll be other uses for yield, we could add a yield x where x is the shiny new feature instead of having all these different keywords for doing mostly the same thing, yield execution.

Frankly, I don't quite understand the 'not yielding execution' argument. After all, isn't the point of calling another method is already to 'yield execution' to that method? Regardless of whether it is asynchronous or not? I'm I missing something here?

And good for you if the async returns synchronously but having the keyword there should signify that there's a likely chance that the method would run asynchronously and that you'll be yielding execution to another method. Your method should account for that regardless of whether the method actually does asynchronous calls or not.

IMO I think the various 'not yielding' cases are an implementation detail. I'd rather vouch for consistency in the language (i.e. reusing yield).


How about complete, as in "I want the task completed"?

Task<byte[]> downloadTask = DownloadFileAsync(url);
byte[] data = complete downloadTask;
  • 1
    Why the downvote? It's a courtesy to at least explain yourself after downvoting. Commented Nov 2, 2010 at 21:11

task (for method declaration) and async (within method body)


Not the answer you're looking for? Browse other questions tagged or ask your own question.