Asynchrony in C# 5, Part Three: Composition


I was walking to my bus the other morning at about 6:45 AM. Just as I was about to turn onto 45th street, a young man, shirtless, covered in blood ran down 45th at considerable speed right in front of me. Behind him was another fellow, wielding a baseball bat. My initial thought was “holy goodness, I have to call the police right now!”

Then I saw that the guy with the baseball bat was himself being chased by Count Dracula, a small horde of zombies, a band of pirates, one medieval knight, and bringing up the rear, a giant bumblebee. Apparently some Wallingford jogging club got into the Hallowe’en spirit this past weekend.

In unrelated news: we’ve had lots of great comments and feedback on the async feature so far; please keep it coming. It is being read; it will take weeks to digest it and volume of correspondence may preclude personal replies, for which I apologize, but that’s how it goes.

Today I want to talk a bit about composition of asynchronous code, why it is difficult in CPS, and how it is much easier with “await” in C# 5.

I need a name for this thing. We named LINQ because it was Language Integrated Query. For now, let’s provisionally call this new feature TAP, the Task Asynchrony Pattern. I’m sure we’ll come up with a better name later; remember, this is still just a prototype. (*)

The example I’ve been using so far, of fetching and archiving documents was obviously deliberately contrived to be a simple orchestration of two asynchronous tasks in a void returning method. As we saw, when using regular Continuation Passing Style it can be tricky to orchestrate even two asynchronous methods. Today I want to talk a bit about composition of asynchronous methods. Our ArchiveDocuments method was void returning, which simplifies things greatly. Suppose that ArchiveDocuments was to return a value, say, the total number of bytes archived. Synchronously, that’s straightforward:

long ArchiveDocuments(List<Url> urls)
{
    long count = 0;
    for(int i = 0; i < urls.Count; ++i)
    {
        var document = Fetch(urls[i]);
        count += document.Length;
        Archive(document);
    }
    return count;
}

Now consider how we’d rewrite that asynchronously. If ArchiveDocuments is going to return immediately when the first FetchAsync starts up, and is only going to be resumed when the first fetch completes, then when is the “return count;” going to be executed? The naive asynchronous version of ArchiveDocuments cannot return a count; it has to be written in CPS too:

void ArchiveDocumentsAsync(List<Url> urls, Action<long> continuation)
{
  // somehow do the archiving asynchronously,
  // then call the continuation
}

And now the taint has spread. Now the caller of ArchiveDocumentsAsync needs to be written in CPS, so that its continuation can be passed in. What if it in turn returns a result? This is going to become a mess; soon the entire program will be written upside down and inside out.

In the TAP model, instead we’d say that the type that represents asynchronous work that produces a result later is a Task<T>. In C# 5 you can simply say:

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

and the compiler will take care of all the rewrites for you. It is instructive to understand exactly what happens here. This will get expanded into something like:

Task<long> ArchiveDocuments(List<Url> urls)
{
  var taskBuilder = AsyncMethodBuilder<long>.Create();
  State state = State.Start;
  TaskAwaiter<Document> fetchAwaiter = null;
  TaskAwaiter archiveAwaiter = null;
  int i;
  long count = 0;
  Task archive = null;
  Document document;
  Action archiveDocuments = () =>
  {
    switch(state)
    {
      case State.Start:        goto Start;
      case State.AfterFetch:   goto AfterFetch;
      case State.AfterArchive: goto AfterArchive;
    }
    Start:
    for(i = 0; i < urls.Count; ++i)
    {
      fetchAwaiter = FetchAsync(urls[i]).GetAwaiter();
      state = State.AfterFetch;
      if (fetchAwaiter.BeginAwait(archiveDocuments))
        return;
      AfterFetch:
      document = fetchAwaiter.EndAwait();
      count += document.Length;
      if (archive != null)
      {
        archiveAwaiter = archive.GetAwaiter();
        state = State.AfterArchive;
        if (archiveAwaiter.BeginAwait(archiveDocuments))
          return;
        AfterArchive:
        archiveAwaiter.EndAwait();
      }
      archive = ArchiveAsync(document);
    }
    taskBuilder.SetResult(count);
    return;
  };
  archiveDocuments();
  return taskBuilder.Task;
}

(Note that we still have problems with the labels being out of scope. Remember, the compiler doesn’t need to follow the rules of C# source code when it is generating code on your behalf; pretend the labels are in scope at the point of the goto. And note that we still have no exception handling in here. As I discussed last week in my post on building exception handling in CPS, exceptions get a little bit weird because there are *two* continuations: the normal continuation and the error continuation. How do we deal with that situation? I’ll discuss how exception handling works in TAP at a later date.)

Let me make sure the control flow is clear here. Let’s first consider the trivial case: the list is empty. What happens?  We create a task builder. We create a void-returning delegate. We invoke the delegate synchronously. It initializes the outer variable “count” to zero, branches to the “Start” label, skips the loop, tells the helper “you have a result”, and returns. The delegate is now done. The taskbuilder is asked for a task; it knows that the task’s work is completed, so it returns a completed task that simply represents the number zero.

If the caller attempts to await that task then its awaiter will return false when asked to begin async operations, because the task has completed. If the caller does not await that task then… well, then they do whatever they do with a Task. Eventually they can ask it for its result, or ignore it if they don’t care.

Now let’s consider the non-trivial case; there are multiple documents to archive. Again, we create a task builder and a delegate which is invoked synchronously. First time through the loop, we begin an asynchronous fetch, sign up the delegate as its continuation, and return from the delegate. At that point the task builder builds a task that represents “I’m asynchronously working on the body of ArchiveDocumentsAsync” and returns that task. When the fetch task completes asynchronously and invokes its continuation, the delegate starts up again “from the point where it left off” thanks to the magic of the state machine. Everything proceeds exactly as before, in the case of the void returning version; the only difference is that the returned Task<long> for ArchiveDocumentsAsync signals that it is complete (by invoking its continuation) when the delegate tells the task builder to set the result.

Make sense?

Before I continue with some additional thoughts on composition of tasks, a quick note on the extensibility of TAP. We designed LINQ to be very extensible; any type that implements Select, Where, and so on, or has extension methods implemented for them, can be used in query comprehensions. Similarly with TAP: any type that has a GetAwaiter that returns a type that has BeginAwait, EndAwait, and so on, can be used in “await” expressions. However, methods marked as being async can only return void, Task, or Task<T> for some T. We are all about enabling extensibility on consumption of existing asynchronous things, but have no desire to get in the business of enabling production of asynchronous methods with exotic types. (The alert reader will have noted that I have not discussed extensibility points for the task builder. At a later date I’ll discuss where the task builder comes from.)

Continuing on: (ha ha ha)

In LINQ there are some situations in which the use of “language” features like “where” clauses is more natural and some where using “fluent” syntax (“Where(c=>…)“) is more natural. Similarly with TAP: our goal is to enable use of regular C# syntax to compose and orchestrate asynchronous tasks, but sometimes you want to have a more “combinator” based approach. To that end, we’ll be making available methods with names like like “WhenAll” or “WhenAny” that compose tasks like this:

    List<List<Url>> groupsOfUrls = whatever;
    Task<long[]> allResults = Task.WhenAll(from urls in groupsOfUrls select ArchiveDocumentsAsync(urls));
    long[] results = await allResults;

What does this do? Well, ArchiveDocumentsAsync returns a Task<long>, so the query returns an IEnumerable<Task<long>>. WhenAll takes a sequence of tasks and produces a new task which asynchronously awaits each of them, fills the result into an array, and then invokes its continuation with the results when available.

Similarly we’ll have a WhenAny that takes a sequence of tasks and produces a new task that invokes its continuation with the first result when any of those tasks complete. (An interesting question is what happens if the first one completes successfully and the rest all throw an exception, but we’ll talk about that later.)

There will be other task combinators and related helper methods; see the CTP samples for some examples. Note that in the CTP release we were unable to modify the existing Task class; instead we’ve provisionally added the new combinators to TaskEx. In the final release they will almost certainly be moved onto Task.

Next time: No, seriously, asynchrony does not necessarily involve multithreading.

(*) I emphasize that this is provisional and for my own rhetorical purposes, and not an official name of anything. Please don’t publish a book called “Essential TAP” or “Learn TAP in 21 Time Units” or whatever. I have a copy of “Instant DHTML Scriptlets” on my bookshelf; Dino Esposito writes so fast that he published an entire book between the time we mentioned the code name of the product to him and we announced the real name. (“Windows Script Components” was the final name.)

Comments (51)

  1. Bryan Rasmussen says:

    You really thought "Holy Goodness"?!?

  2. Stuart says:

    Can you explain why you decided to make the "Task<>" part of the return type explicit rather than implicit?

    Why not make it so that "async long ArchiveDocuments(…)" would automatically translate into a method that really returns Task<long>?

    It seems very odd to me to be able to write "return count;", where count is a long, in a method that doesn't return anything convertible from long. But it doesn't seem odd at all that "async long" means something different than just "long" and therefore what you actually get is a different type – especially considering that the shorthand for eventually retrieving the value converts it straight back anyway.

  3. Jon Skeet says:

    @Stuart: I think it makes sense for the method's return type to *really* be the method's return type.

    Also, in your proposed syntax how would you differentiate between the two method declarations which are currently:

       async void FireAndForget()

    and

       async Task FireAndKeepTrackOfCompletion()

    Both represent an async method with no "result" as such – but the latter returns a task so that you can see when it's done. Aside from anything else, this affects how exceptions are propagated.

  4. Stuart says:

    @Jon – I suppose I don't understand the value in the difference between those two. Surely it's the *caller*, not the method being called, that knows whether it cares about when the method completes or not?

  5. Jon Skeet says:

    @Stuart: No, the method itself cares too.

    Consider what happens within the method if an exception is thrown. If the method is declared to return void, the exception will be thrown up the stack – whether that's to the original caller or a continuation caller. If the method is declared to return Task, the task itself will contain the exception, and the method will just return.

    Now you might want to argue against that feature, but it's a feature which currently exists in the CTP, and which isn't handled by your suggestion of changing the return type declaration.

    (It's not the most important argument against that, mind you – I'd just say it's clearer if you can tell what a method will *actually* return just from looking at its declared return type.)

  6. Dave Sexton says:

    Speaking about composition, how about showing some love for Rx?

    async IObservable<Document> ArchiveDocumentsAsync(List<Url> urls)

    {

    long count = 0;

    Task archive = null;

    Document previousDocument;

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

    {

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

    count += document.Length;

    if (archive != null)

    {

    await archive;

    yield return previousDocument;

    }

    previousDocument = document;

    archive = ArchiveAsync(document);

    }

    }

  7. Daniel says:

    @Stuart: Think about an async method implementing an interface method.

    The interface method will be declared as "Task<long> ArchiveDocuments(List<Url> urls);", so the code implementing the interface should use the same method signature (no matter whether it's implemented using 'async').

    @Dave Sexton: Sorry, but IObservable won't work for this purpose. Just like IEnumerable doesn't allow the producer of the enumeration to await something (MoveNext() returns bool); IObservable doesn't allow the consumer to await something.

    I'd like to have support for this, but it will have to use a new interface (IAsyncEnumerable?); IObservable isn't suited for the task.

  8. John Peters says:

    "Now consider how we'd rewrite that asynchronously. If ArchiveDocuments is going to return immediately when the first FetchAsync starts up, and is only going to be resumed when the first fetch completes, then when is the "return count;" going to be executed? The naive asynchronous version of ArchiveDocuments cannot return a count; it has to be written in CPS too"

    I think looking into the Enterprise library (for examples of Cross-concerns like validation on entry to a method call for parameter correctness) or the Spring.NET framework could simplify this for a programmer as follows, using Attributes:

    [Task CallBack=MethodName]

    void ArchiveDocumentsAsync(List<Url> urls, Action<long> continuation)

    {

     // somehow do the archiving asynchronously,

     // then call the continuation

    }

    Where the attribute handles cross-concerns.  The Callback parameters could be overridden to allow either a methodName for call back that must have the signature of the return of the method that is attributed,  or it could also have a "NextLine" meaning return to next line of invoker.  Shoot it could even have multiple conditions, like "IF this" Return here, or "IF that return there, all contained in the attribute.

    We know from refelection that we can determine what method called us, the Stack knows the line of code calling us, so why not make this a cross-concern and leave the developer free of the internals of Aysnc states?

    Just a thought.

  9. @Stuart: "Can you explain why you decided to make the "Task<>" part of the return type explicit rather than implicit?"

    You've had some good answers to that already, but I'd add that it depends on what level of abstraction the user is going to write their code at. Personally I'd quite like it to be a high level (as much of the time as possible). So I'd like to say "this is an async method that returns an int", and write it like that, without having to put Task<> around it.

    I'd also like to be able to call it like that from another async method (i.e. without having to put await). Ideally, by default, the "plumbing" would be hidden. A method call should work like a method call: it should await the result of the method, just like any method call does.

    Of course this would raise other difficulties, because there now has to be a special way to get hold of the raw Task<> for when you want to use combining operators on it. Also there would need to be a more solid way of deciding that a method should be treated as async. If "awaiting" were to be automatically triggered by the compiler, then just sniffing the return type for certain methods is too vague. And there are probably a ton of other problems to be solved before this could be a reality.

    But that's how I'd like it to be. If you don't want to wait for the method to complete, that should be something you explicitly ask for. But if you want to wait for the method to complete, just call it like a method.

    @Daniel "Think about an async method implementing an interface method."

    How about:

    interface IThings

    {

       async int GetCount(); // compiler knows to translate this to Task<int>

    }

  10. Dave Sexton says:

    @Daniel: "IObservable doesn't allow the consumer to await something".

    I disagree; it certainly does.  As a matter of fact,  Observable.CreateWithDisposable is a call/cc implementation, just like await.

  11. Stuart says:

    @Daniel and Daniel…

    "interface IThings

    {

      async int GetCount(); // compiler knows to translate this to Task<int>

    }"

    Perfect – and it'd be perfectly permissible for someone who knew what they were doing to implement that method by writing a regular method that returned Task<int> rather than an async method that returned int.

  12. Blake says:

    +1 on the "don't repeat yourself" view that "async int Foo()" should be how you write an async method returning Task<int>.   (And just drop the void returing async functions – but then, I'd rather have a proper System.Unit and drop the non-generic Task returns as well.)

  13. Further to the "automatic awaiting" idea… this is my thinking so far:

    Keep the existing CPS design as is: the await keyword can operate on any Task (or Task-like) object and makes the compiler generate the continuation logic.

    But in addition, invent an attribute that can go on methods, something like [AutoAwait]. The compiler would put this attribute on methods marked with the async modifier. For such methods, where they are called, the compiler behaves as if they had an await in front of the method call: there is no need to specify it explicitly.

    And if you want to get hold of the Task from such a method, prefix it with a new keyword: start. This operator only applies to method calls, and effectively opts out of awaiting for methods where the default is to await.

    This way, when I write a method call, it behaves like a method call – it awaits a result, without me having to ask it to. This happens regardless of the underlying plumbing. But if I want to get clever and start a "background operation", I can still do so, by saying "start" before the method call.

  14. Hmm, when I said "CPS design" I should of course have said TAP (tm!)

  15. And one more thing: an attempt to call an [AutoAwait] method from any context other than an async method should cause a compile error: to fix it, you have to prefix it with the start operator. This forces the user to write code that can be copied/pasted between async and non-async contexts without changing the behaviour unnecessarily.

  16. Dave Sexton says:

    FYI, the IObservable discussion has continued here:

    social.msdn.microsoft.com/…/1b74834c-7979-45a5-bd39-447a8848aa76

  17. Omer Mor says:

    Eric, I understand that you don't want extensibility on the production of asynchronous methods:

      "but have no desire to get in the business of enabling production of asynchronous methods with exotic types"

    However, the decision to go with a concrete class instead of an interface prevents the use of generic covariance.

    Furthermore, as Dave Sexton wrote, the marriage with Tasks will make the Rx IObservable monad a second class citizen.

    As it seems, different groups in MS are trying to solve the asynchronous programming problem, and came up with several different and overlapping solutions: Tasks, Rx, TPL Dataflow (the successor to CCR?), and the countless previous efforts: Delegate.BeginInvoke, BackgroundWorker, IAsyncResult, …

    Personally I find Rx to be the most general and mature approach – It could sure use some language love (like you did with IEnumerable and iterator blocks)!

  18. Omer Mor says:

    Eric, I understand that you don't want extensibility on the production of asynchronous methods:

      "but have no desire to get in the business of enabling production of asynchronous methods with exotic types"

    However, the decision to go with a concrete class instead of an interface prevents the use of generic covariance.

    Furthermore, as Dave Sexton wrote, the marriage with Tasks will make the Rx IObservable monad a second class citizen.

    As it seems, different groups in MS are trying to solve the asynchronous programming problem, and came up with several different and overlapping solutions: Tasks, Rx, TPL Dataflow (the successor to CCR?), and the countless previous efforts: Delegate.BeginInvoke, BackgroundWorker, IAsyncResult, …

    Personally I find Rx to be the most general and mature approach – It could sure use some language love (like you did with IEnumerable and iterator blocks)!

  19. Keith Farmer says:

    @Daniel:  So how would you progressively compose a new Task?

    Take Eric's WhenAll example as a basis.  The automatic invocation approach gets very annoying at that point, but it's a key scenario to async processing.

  20. @Keith J. Farmer

    Here's Eric's WhenAll example in its original form:

    List<List<Url>> groupsOfUrls = whatever;

    Task<long[]> allResults = Task.WhenAll(from urls in groupsOfUrls select ArchiveDocumentsAsync(urls));

    long[] results = await allResults;

    And here it is modified to account for the posited [AutoAwait] attribute on ArchiveDocumentsAsync:

    List<List<Url>> groupsOfUrls = whatever;

    Task<long[]> allResults = Task.WhenAll(from urls in groupsOfUrls select start ArchiveDocumentsAsync(urls));

    long[] results = await allResults;

    I just stick 'start' in front of the thing I want to start. That way, it's clear that I'm starting something that I'm not immediately going to wait for a result from. If I want to wait for a result from a method call, that's what the existing method call notation implies.

    More thoughts here (async delegates!):

    programmers.stackexchange.com/…/15796

  21. Keith Farmer says:

    @Daniel:  This example just crossed my inbox as a very strong reason why we should not have automatic invocation:

    Given overloads:

    void PublishMovie(Movie)

    void PublishMovie(Task<Movie>)

    and call:

    PublicMovie(GetMovieAsync())

    .. which overload should be called?

  22. Keith Farmer says:

    @Daniel:  so you've increased the amount of typing I have to do, just to perform the same function? 🙂

  23. Keith Farmer says:

    @Daniel:  so you've increased the amount of typing I have to do, just to perform the same function? 🙂

  24. MikePopoloski says:

    @Keith J. Farmer: The first would get called, since you didn't use Daniel's proposed "start" keyword to indicate that you wanted a task instead.

    One unrelated thing I wanted to ask is whether anyone finds having to check for null to be as ugly as I do. Surely the compiler could do that for us?

  25. MikePopoloski says:

    To clarify: I mean checking for null before using the "await" keyword.

  26. Keith Farmer says:

    @Mike:  And that really hurts the composition model for the sake of making me type more.

    Further, I've now become convinced of the wisdom *against* using an attribute marker for this.  It causes differentiation with pre-existing code.  For it to be callable in the same way as new code would require a gratuitous re-compile.  In the case of code that requires certification, that's hideously expensive.

    "[AutoAwait]" and "start" are pretty much non-starters, as it were.

  27. Keith Farmer says:

    @Mike:  null check — example code?  What should be the default response to finding null, which would be a different response from what happens now?

  28. Stuart says:

    @Keith, I understand your concern about "start" but don't you think there's at least a tradeoff involved? I'd think that with more people using async methods there will be a lot of confusion involved, and I can absolutely see people being confused about what they are getting when they call FooAsync(). "start" (or "begin" which was what I was going to propose for the same thing until I read Daniel's suggestion) makes it possible to be unambiguous about what you want.

    On the other hand, I don't favor [AutoAwait] – I think you should have to specify what you want *either way*. So, when calling an async method you have to *either* invoke it as "begin FooAsync();" or as "continue after FooAsync();" (to pick my favorite of the suggestions for "await" replacements to date). Leaving off both would result in a warning, although the code would still compile. There's precedent for that in virtual methods, where you can disambiguate with either "new" or "override" but if you don't specify either you get a warning.

    With this proposal, the only difference between calling pre-existing code and calling newly-compiled code would be the lack of the warning if you omit "begin" or "continue after".

  29. @Keith J. Farmer

    PublicMovie(GetMovieAsync())  //  get a Movie, pass it to suitable overload

    PublicMovie(start GetMovieAsync()) // get a Task<Movie>, pass it to suitable overload

    It's pretty straightforward. You have to think of async methods as an alternative implementation of the concept of a method. They add a certain extra valuable capability: they can be started, as well as merely called. But when you're merely calling them, they're the same concept, and so the same notation would be ideal.

    As for the downside of using an attribute marker… since this occurred to me at the weekend, I've already become quite used to fending off complaints about my implementation suggestions! 🙂 Regardless of the implementation, the desired outcome is the same, and I think it makes perfect sense: let people work at a higher level of abstraction. Let the notation speak for itself. A method call is a method call. A return value is a return value. If you want something else, you ask for it explicitly.

    That said, I don't think it's exactly a showstopper that existing assemblies have to be rebuilt to take advantage of new features. Remember that this suggestion is merely an *addition* to the existing CTP work. You could still use await on methods that don't have the attribute.

    Also you could presumably write an extension method to fix libraries you weren't able to fix properly:

    [AutoAwait]

    public Task<Movie> GetMovieAsync(this MovieDatabase mdb)

    {

       return mdb.GetMovie();

    }

    Doesn't really seem like a big deal to me – and it would be a short term problem, not a long term one.

  30. @Stuart: So, when calling an async method you have to *either* invoke it as "begin FooAsync();" or as "continue after FooAsync();"

    Does this part of my last comment persuade you at all?

    "You have to think of async methods as an alternative implementation of the concept of a method. They add a certain extra valuable capability: they can be started, as well as merely called. But when you're merely calling them, they're the same concept, and so the same notation would be ideal."

    Or to put it another way: calling a method *already* means wait for the result. Imperative coding is a notation for doing one thing at a time. Why introduce another? We only need the new notation when we are diverging from that.

    (By the way, await is *not* the opposite of start. The 'start' prefix can only apply to a method invocation, whereas await applies to an object representing an operation in progress.)

  31. Keith Farmer says:

    @Daniel:  recompilation absolutely is a show stopper for a lot of people.  Not me — I don't spend $100k certifying a piece of software to meet government standards — but for a lot of other people it is.

    Were we discussing a proposed feature for C#1, I don't think there's be as much of an issue, because we could (rightly) expect no legacy code to support.

    But back to 'start'.  I do not believe that the most-used operation is actually the fetching of the result.  It's the composition of the task.  Given that, the invocation marker needs to be at the end, not the beginning.  That is, by default you get the composition unit, not the evaluation result.

    We see this same pattern with LINQ as it's typically implemented:  we favor composition, and provide (pre-existing, in this case) sugar to call GetEnumerator().

  32. Ruben says:

    I'd really like to see an async foreach; one of the frequent samples is using a for-loop to demonstrate the power of async/await. But what about a foreach that streams its results in an async fashion?

    interface IAsyncEnumerator : IEnumerator, IDisposable

    {

       async bool MoveNextAsync();

    }

    Then the following code

    foreach async (T elem in asyncColl)

    {

       …

    }

    could be translated to

    using (IAsyncEnumerator e = (IAsyncEnumerator) asyncColl.GetEnumerator())

    {

       while (await e.MoveNextAsync())

       {

           T elem = e.Current;

           …

       }

    }

    Now, that would also suggest supporting a syntax to create such IAsyncEnumerators through the existing iterator support. A yield async x…? Or explicitly returning an IAsyncEnumerable<T>/IAsyncEnumerator<T> rather than an IEnumerable<T>/Enumerator<T>?

    That would be truly awsome.

  33. Stuart says:

    @Daniel: "You have to think of async methods as an alternative implementation of the concept of a method. They add a certain extra valuable capability: they can be started, as well as merely called. But when you're merely calling them, they're the same concept, and so the same notation would be ideal."

    I think that's the whole reason why I don't like "await" as a keyword. Because, if I'm understanding this series of posts correctly, "merely calling them" (and awaiting the result) is precisely what you're *not* doing. You're starting them and then specifying what will happen after they are complete. An "await" doesn't signify a blocking call to a method. It's similar to one, but it's not quite the same semantics. So I'm not in favor of the difference between them being elided entirely.

    Also, if I understand rightly, "await" can only be used inside an async method. If you made "await" unnecessary and implied, then you'd have methods that could (effectively) only be called from async methods, without any clear syntactic reason why.

    (Point taken about await not being the opposite of start)

  34. Alexey says:

    Can you please explain a little bit why you only target async operations by this pattern?

    For me all these continuations, etc. looks like an "async" monad in F# ported into C#, and because there is no such syntax in C#, you have to introduce two new keywords.

    in F# world it is:

    let MyFunction =

       async {

           …

           let! value = GetAsyncValue();

           …

       }

    So the question is, why do not introduce keywords that allow us to deal with any monad, not just async?

    the "async" modifier become just a name of the monad, and "await" is nothing more than "let!", which represents the "Bind" operation, isn't it?

    It would be really interesting to know your thoughts about it.

  35. @Stuart:

    > Because, if I'm understanding this series of posts correctly, "merely calling them" (and awaiting the result) is precisely what you're *not* doing. You're starting them and then specifying what will happen after they are complete. An "await" doesn't signify a blocking call to a method.

    Although 'await' in front of a method invocation doesn't mean "blocking" at the CLR level, it does mean "put in the necessary plumbing to resume when we have the logical return value of the method we're invoking" – and that's the return value that would be obtained when the called method reaches a return statement (if that method is also an async C# method). This is really the same thing that the CLR does with its built-in implementation of stacks, method calls and threads. It's just implemented differently, giving us greater control over the way our methods execute, instead of them being tied to threads and stacks.

    In C# today, when a method calls another method, what happens? The execution of the calling method is paused, the called method begins executing. When the called method finishes executing, the execution of the calling method is resumed and the return value of the called method is available. That's what a method call means.

    > Also, if I understand rightly, "await" can only be used inside an async method. If you made "await" unnecessary and implied, then you'd have methods that could (effectively) only be called from async methods, without any clear syntactic reason why.'

    I mention that on the programmers.stackexchange answer I linked to previously. The compiler could simply behave exactly as it does today outside of async methods. Nothing would be taken away at all. However, I think it might be worth requiring the caller to put the 'start' prefix in front of a call to an [AutoAwait] method when the call is not in an async method. It has the virtue of making code retain the same meaning when it is copied and pasted between async and non-async methods.

  36. Bradley Grainger says:

    I'm surprised that the last ArchiveAsync operation (in ArchiveDocumentsAsync) isn't awaited; I would have expected to see "if (archive != null) await archive;" right before "return count;". I know that it *can* run in parallel with the total count of bytes being returned to the caller (so ArchiveDocumentsAsync doesn't *need* to await it), but it certainly feels odd that the caller has no way to catch an exception thrown by that last ArchiveAsync call, and has no guarantees that the archiving has actually finished.

    Or maybe this is just contrived sample code and I shouldn't be too picky about the style…

  37. SergeyA says:

    Is cancellation supported with TaskEx.Run method?

    Consider the following code:

       public partial class MainWindow : Window

       {

           public MainWindow()

           {

               InitializeComponent();

           }

           private CancellationTokenSource cancelationRoute;

           private async void Button_Click(object sender, RoutedEventArgs e)

           {

               var btn = sender as Button;

               if(btn.Name=="btnDoWork")

               {

                   btnDoWork.IsEnabled = false;

                   lblResult.Content = string.Empty;

                   await DoWork();

               }

               else if(btn.Name == "btnCancel")

               {

                   cancelationRoute.Cancel();

               }

           }

           private async Task DoWork()

           {

               Task<string> task;

              try

              {

                  cancelationRoute = new CancellationTokenSource();

                  task = TaskEx.Run<string>(CopyFile, cancelationRoute.Token);

                  await task;

                  lblResult.Content = task.Status.ToString();

                  btnDoWork.IsEnabled = true;

              }

              catch(OperationCanceledException)

              {

                  lblResult.Content = "canceled";

                  btnDoWork.IsEnabled = true;

                  return;

              }

              cancelationRoute = null;

           }

           private string CopyFile()

           {

               Enumerable.Repeat(100, 50).ToList().ForEach(Thread.Sleep);

               return "Ok, I finished!";

           }

       }

    }

    This is code-behind of simple UI consists of two buttons "Do Work" and "Cancel" and result label.

    If I click Do Work button, everything is fine – the UI is responsive and 5 seconds later the result label shows "RanToCompletion" status.

    But cancellation does not work. Even though I click Cancel which calls to cancelationRoute.Cancel() while the task is run, the task ends up with RanToCompletion status.

    Am I doing something wrong?

  38. Ilya says:

    Hi,

     Sorry for off topic :*)

     I see that you are stick with the new aynch feature for a while, but I have a struct related question I eager to have an answer to and google is unable to help me. I hope you will give me a good link at least. Please!

     I'm trying to get what I call measurement units system by wrapping double into struct. I have C# structures Meter, Second, Degree, etc. My original idea was that after compiler has inlined everything I would have a performance the same as if double were used.

     My explicit and implicit operators are simple and straightforward, and compiler does actually inline them, yet the code with Meter and Second is 10 times slower than the same code using double.

     My question is being: why cannot C# compiler make the code using Second as optimal as the code using double if it inlines everything anyway?

      Second is defined as following:

    struct Second

    {

      double _value; // no more fields.

      Second operator + (Second left, Second right) { return left._value + right._value; }

      // plenty of simple operators

    }

  39. Jon Skeet says:

    @Ilya: I suggest you ask on Stack Overflow instead – it's not really relevant here.

  40. Daryl says:

    Eric,

    Looks nice.  Does this mean that Silverlight and Phone7 are finally going to get access to the task parallel library?

  41. Mr. Javaman says:

    Any comments on my earlier post of using Attributes for Asynch work?

  42. Joren says:

    @Alexey "So the question is, why do not introduce keywords that allow us to deal with any monad, not just async?"

    Because that already exists: the LINQ syntax allows you to do exactly that.

  43. Stuart says:

    @Daniel – "In C# today, when a method calls another method, what happens? The execution of the calling method is paused, the called method begins executing. When the called method finishes executing, the execution of the calling method is resumed and the return value of the called method is available. That's what a method call means."

    It's taken a few days for this concept to sink in properly but I see what you're saying now. Sorry that it took me so long. I was so busy trying to turn myself inside out to understand CPS that I forgot to turn myself right-side out again afterwards 😉

    Perhaps the appropriate keyword, then, isn't something that talks explicitly about control flow, like "continue after" or whatever, OR something that implies asynchrony like "await", but something that just says "do the whole of" or "fully execute" or "complete".

    var document = complete FetchAsync(url);

    var document = finish FetchAsync(url);

    var document = do FetchAsync(url);

    var document = invoke FetchAsync(url);

    I think I like "finish" best of these, because then you get:

    if (archive != null) finish archive;

    Plus there's a lovely symmetry with:

    var archive = start ArchiveAsync(document);

    The more I think about this whole thing, the more it worries me that you can only effectively call async methods (in the most natural way) from within other async methods. That's going to make interoperability with non-async code a nightmare – especially where you have to implement an interface that expects a return value. It seems like the "async" modifier might become viral, increasingly needing to be applied to more and more methods because they want to call other async methods, until you can't do anything useful without it. (If I'm right about that, it means that the limitation that you can't write an async iterator method may be a bigger problem than it appears at first glance…)

    I wonder if there'd be some value in having at least partial support for the "finish" keyword in non-async methods (perhaps only when applied directly to a method invocation, not to an existing Task?), but implemented by use of a library method that invokes the task on a separate thread and blocks until it completes.

  44. Gabe says:

    Stuart: You are correct that "await" (or "finish" as you'd have it) is contagious. Anything that uses it must be async, causing all of its callers to be async, and so on. So how do you get a Task's result from a non-async method? You just get the Task.Result property (or call Task.Wait() for void methods), which is just what you'd do in C# 4 because it only has non-async methods.

    So with the CTP you can write:

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

    to get the URL while other stuff executes on the thread, or you can write:

    var document = FetchAsync(urls[i]).Result;

    and the thread will sit there waiting until the URL is fetched.

  45. Stuart says:

    So maybe "await" should simply translate into ".Result" when written inside a non-async method?

  46. gauravmathur says:

    I have a suggestion with a reason for syntactically improving the constructs.

    Return statement in async method in reality is returning a value which is getting associated with Task and not something which looks like it is returning TO THE CALLER.

    async public Task<int> ReturnIntAsync()

    {

          return 0;

    }

    So the return statement can be modified something like

    async return OR task return, just to clarify what it is doing and also matches with the function signature.

    I have tried to explain this in my blog(my first blog:), please have a look.

    gauravsmathur.wordpress.com/…/something-wrong-with-async-await-and-the-tasktask

  47. Mr. Javaman says:

    I still think this design should move to attribute level instead of implmenting Async specific stuff inside the worker threads…. Thoughts?

  48. @Stuart, it's hard to be certain but I don't know if you're thinking the same thing as me! 🙂

    Yes, await (or 'finish' if you prefer) has to be retained so that we can explicitly force a continuation on any Task-like object. But in examples like this:

    var document = await FetchAsync(url);

    … the await prefix ought to be redundant (indeed, erroneous), just as it would be in a non-async method. The established C# syntax to indicate that you want to call a method and wait for it to complete, and bind the result to a name:

    var document = Fetch(url);

    (And the naming convention becomes less necessary too – the very fact that a naming convention is invoked is a signal that a FACT exists, which could be captured in a more formal way, so allowing our tools to be more helpful.)

    All my previous comments under this post have been about extending that familiar syntax so it works in this new, closely analogous situation and means the same thing on a logical level (the technical detail having been abstracted away).

    Re: the viral nature of async calls, yes, that's unavoidable, because the CLR has an existing model of method calls and stacks that works a certain way. C# has to continue to integrate with it.

    C# could – in theory – compile every method as async, and generate a continuation step for every method call. This would make C# class libraries incompatible with other CLR languages, and so is not really a practical option. We have to have two "modes" of compilation in order to be able to interoperate smoothly on both the CLR and async levels.

    But it's a useful thought experiment. In this parallel universe (pun definitely not intended), awaiting would be implied by every (normal) method call – in other words, the compiler would put [AutoAwait] on every method written in C#. A key point is that the semantics of all existing code would be identical.

    And of course even your Main function would be async. To allow your program to run under the CLR, the compiler would have to quietly generate the "real" Main function for you, which would keep a stack of continuations in order to simulate the normal semantics of method calls for you.

    A similar thing would have to happen whenever you assigned one of your methods to an ordinary delegate (this would include starting threads). If you declared a delegate type of your own, it would have to be translated into an async delegate (marked with [AutoAwait] and transformed so it returns Task<T>, etc.)

    In other words, there would be a lot of extra work for the compiler to do! And the result would have poor interoperability with other CLR languages. For example, a property getter would have to be turned into a method that returned a Task<T>, and so would no longer look like a property to other CLR languages.

  49. Daryl says:

    @Daniel Earwicker:

    The await would only be redundant if you *always* wanted to wait for the result.  There's another option, which is to start a long-running process (Task), do some other things, and later await the result.  For example:

    var bigSlowDocumentTask = FetchAsync(url);

    ….

    (do some other stuff, possibly starting other tasks and awaiting other things)

    ….

    var document = await bigSlowDocumentTask;

    In fact, there are three paradigms here for calling a method:

    1. var result = Method(); — call the method, wait for the result, and block the current thread until it arrives.

    2. var result = await MethodAsync(); — call the method, wait for the result, and let the current thread do other things until it arrives.

    3. var task = MethodAsync(); — call the method, don't wait for the result, do other things, and plan to check in on it later, possibly cancelling or awaiting it at some point in the future.  *This calling paradigm can be used in a non-async method*.

  50. Bob says:

    The compiler creates goto's  "(SCREAM)"

    What else would you have the compiler create? When generating code the compiler only has one local, non-exception control flow at its disposal, and that's goto (either conditional or unconditional). Remember, conditional and looping statements are just more pleasant ways to write gotos; they are still gotos when the compiler is done with them. What else would they be? – Eric