Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

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.

share|improve this question
    
By the way "language-integrated asynchronous programming" gives us LIAP, doesn't quite roll off the tongue the same way as LINQ ;) –  Benjol Oct 29 '10 at 20:51
1  
Unless its pronounced leap. –  Conrad Frix Oct 29 '10 at 21:17
3  
But "Language-Integrated Asynchronous Runtime" acronyms up nicely. –  glenatron Oct 29 '10 at 22:06
    
This has got to be off-topic. –  DeadMG Jan 24 '12 at 4:45
add comment

closed as not constructive by Mark Trapp Feb 2 '12 at 0:26

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.If this question can be reworded to fit the rules in the help center, please edit the question.

13 Answers

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

share|improve this answer
    
This answer is a bit late, they settled on async and await a year ago. –  Jay Elston Feb 2 '12 at 0:33
add comment

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.

share|improve this answer
    
It's really hard to argue with the simplicity here. –  sblom Jan 24 '12 at 4:05
add comment

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

share|improve this answer
    
Hmmm, perhaps finish would be even better than start? –  Protagonist Nov 6 '10 at 10:19
add comment

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.

Update

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.:

[AutoAwait]
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.

share|improve this answer
    
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 Nov 1 '10 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. –  Daniel Earwicker Nov 1 '10 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 Nov 1 '10 at 19:21
    
I like your inversion of the await keyword. And I also dislike the triple-redundancy of public async Task<int> FooAsync(). –  Allon Guralnek Nov 1 '10 at 19:50
    
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. –  Daniel Earwicker Nov 2 '10 at 12:28
add comment

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

share|improve this answer
add comment

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

share|improve this answer
    
+1 and by the way, you beat me to commenting on his blog entry by 7 minutes... –  Note to self - think of a name Oct 29 '10 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). –  Allon Guralnek Oct 29 '10 at 23:43
    
@Allon You don't necessarily run the loop body of while(x) {...} either, if x is false. –  Note to self - think of a name Oct 30 '10 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. –  Allon Guralnek Oct 30 '10 at 9:41
    
Is a new keyword necessarily a bad thing? As I understand it, the await keyword would be recognized by context, so you could still have a method or variable named "await" if you wanted to. To some degree, I think using a new keyword for new functionality is less confusing than reusing an existing keyword to mean more than one thing. (exaggerated example: dangermouse.net/esoteric/ook.html) –  Tim Goodman Nov 5 '10 at 18:50
show 1 more comment

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.

share|improve this answer
add comment

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."

share|improve this answer
add comment

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.

share|improve this answer
    
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) –  Note to self - think of a name Oct 30 '10 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 Oct 30 '10 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 Oct 30 '10 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 Nov 1 '10 at 18:48
add comment

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

Task<byte[]> downloadTask = DownloadFileAsync(url);
byte[] data = complete downloadTask;
share|improve this answer
1  
Why the downvote? It's a courtesy to at least explain yourself after downvoting. –  Allon Guralnek Nov 2 '10 at 21:11
add comment

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.

share|improve this answer
1  
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.) –  Eric Lippert Oct 30 '10 at 0:05
1  
@Eric, in F# that would be do!, but you knew that... –  Benjol Oct 30 '10 at 15:41
add comment

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.

share|improve this answer
    
I like resume after for await. Maybe async could be called resumable. –  Tim Goodman Nov 5 '10 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. –  herenvardo Mar 31 '11 at 13:59
add comment
hearken unto AsyncFetch(…)

(if you don't get it, read Eric's blog entry. At least it's better than for sooth Romeo wherefore art thou AsyncFetch(…))

share|improve this answer
    
(those without a sense of humor need not apply) –  Note to self - think of a name Nov 1 '10 at 18:34
add comment

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