Custom awaitables for dummies

Şafak Gür picture Şafak Gür · Sep 30, 2012 · Viewed 8.6k times · Source

In Async/Await FAQ, Stephen Toub says:

An awaitable is any type that exposes a GetAwaiter method which returns a valid awaiter.
...
An awaiter is any type returned from an awaitable’s GetAwaiter method and that conforms to a particular pattern.

So in order to be an awaiter, a type should:

  • Implement the INotifyCompletion interface.
  • Provide a boolean property called IsCompleted.
  • Provide a parameterless GetResult method that returns void or TResult.

(I'm ignoring ICriticalNotifyCompletion for now.)

I know the page I mentioned has a sample that shows how the compiler translates await operations but I'm stil having a hard time understanding.

When I await an awaitable,

  • When is IsCompleted checked? Where should I set it?
  • When is OnCompleted called?
  • Which thread calls OnCompleted?
  • I saw examples of both directly invoking the continuation parameter of OnCompleted and using Task.Run(continuation) in different examples, which should I go for and why?

Answer

Stephen Cleary picture Stephen Cleary · Sep 30, 2012

Why would you want a custom awaiter?

You can see the compiler's interpretation of await here. Essentially:

var temp = e.GetAwaiter();
if (!temp.IsCompleted)
{
  SAVE_STATE()
  temp.OnCompleted(&cont);
  return;

cont:
  RESTORE_STATE()
}
var i = temp.GetResult();

Edit from comments: OnCompleted should schedule its argument as a continuation of the asynchronous operation.