Table of contents
This package provides Coroutine
, a coroutine that can use async/await syntax in C#.
- Coroutines can be written in C# using async/await syntax.
- Coroutines are executed by explicitly calling the runner
Update
, so you can easily control the update timing. - Coroutines can wait for executed coroutines.
- Coroutines can be written inline using asynchronous lambda expressions.
- Coroutines can be canceled.
- When a coroutine is canceled, all coroutines waiting for that coroutine are also canceled together.
- A variety of useful methods are provided as standard.
- If you are concerned about the cost of state machine generation, you can create your own using inheritance.
- The behavior of some processes can be rewritten by using interfaces.
- Computation expressions based on TaskBuilder.fs are provided for F#. (AwaitableCoroutine.FSharp package)
For example, you can define a coroutine as follows
// Coroutine can be created using the async method.
private static async Coroutine CreateCoroutine()
{
while (true)
{
for (var i = 0; i < 5; i++)
{
Console.WriteLine($"Hello {i}");
// Use `Yield` to wait (suspend) with await only once.
await Coroutine.Yield();
}
Console.WriteLine("Start delay");
// Create a coroutine that executes for the specified count, and wait with `await`.
await Coroutine.DelayCount(10);
}
}
And call it as follows.
public static void Main(string[] _)
{
// Create an instance of Runner
var runner = new CoroutineRunner();
// Note: the `Coroutine` must be created in a callback passed to the `Create` or `Context` extension methods
var coroutine = runner.Create(CreateCoroutine);
/*
// When using the `Context` extension method
var coroutine = runner.Context(CreateCoroutine);
*/
// Main loop
while(!coroutine.IsCompletedSuccessfully)
{
// Move registered coroutines to the next by calling the `Update` extension method of ICoroutineRunner
runner.Update();
}
}
Asynchronous lambda expressions can also be used to generate coroutines.
public static void Main(string[] _)
{
var runner = new CoroutineRunner();
// Create an `Coroutine` using an asynchronous lambda expression.
var coroutine = runner.Create(async () => {
for (var i = 0; i < 5; i++)
{
Console.WriteLine($"Hello with async lambda {i}");
await Coroutine.Yield();
}
});
// Note: When using asynchronous lambda expressions in `Context` methods, Explicit declaration of generic parameters is required.
/*
var coroutine = runner.Context<Coroutine>(async () => {
await Coroutine.Yield();
});
*/
while(!coroutine.IsCompletedSuccessfully)
{
runner.Update();
}
}
Note that Coroutine
and Coroutine<T>
are generated in the callback function of the Create
extension method or the Context
extension method.
It is needed to give information about which ICoroutineRunner
the coroutine should be registered with.
Basically, use the Create
extension method.
If you want to return a type other than Coroutine
or Coroutine<T>
, such as returning a tuple of Coroutine
, use the Context
extension method as follows.
var (c1, c2) = runner.Context(() => (Coroutine.DelayCount(1), Coroutine.DelayCount(1)));
Be careful when creating an Coroutine
using asynchronous lambda expressions, because it will be inferred as a Task
if you don't specify the generic parameters.
If you want to give an argument to the creation of a coroutine, you can do so as follows.
Context(() => FooBarCoroutine(arg1, arg2)). var coroutine = runner;
Classes for awaitable coroutines.
See Coroutine.md.
This interface is the context for executing a coroutine.
See ICoroutineRunner.md.
Extension package for F#.