11

By creating one or more awaiters and awaitables, is it possible to build coroutines in C#?

Ideally I would like to be able to write something like:

void async Click() {
  var mouse_position = await left_mouse_click();
  await shoot_projectile();
}

and then obtaining from the Click method something that I can either await inside another async method or that I can explicitly iterate with some MoveNext/GetResult method.

The end goal is that I need to integrate C# async/await with F# monadic coroutines for a game development framework (http://casanova.codeplex.com).

Giuseppe Maggiore
  • 2,011
  • 1
  • 23
  • 31

1 Answers1

7

By creating one or more awaiters and awaitables, is it possible to build coroutines in C#?

Sure! I have a blog post that uses TaskScheduler to build simple coroutines, and Jon Skeet has a blog post that uses custom awaitables to build simple coroutines.

But looking at the rest of your question and comments, I'm not sure if coroutines is what you really want. If you want to "iterate" over awaitables, your best bet is Reactive Extensions (which interoperates well with async). There is no C# language feature for an "async yield".

Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810
  • Yes, that looks like it. I just need to be able to yield inside an async and step through all the resulting yields from an external loop, but I cannot find information on how to do this... – Giuseppe Maggiore Mar 17 '13 at 14:10
  • 1
    `Task`s weren't designed for that. The Rx team started work on an `IAsyncEnumerator` which has the behavior you're describing (there's an old Channel9 video on it), but that work has been all but abandoned because it's almost never the right approach. I recommend you use regular Rx instead. – Stephen Cleary Mar 17 '13 at 14:58
  • By adding the continuation to a global list of continuations that I can then unwind myself inside a custom awaitable I can emulate what I need. I am still forced to return a Task if I want a non-void async method though, and that seems weird! – Giuseppe Maggiore Mar 17 '13 at 20:02