Await is just an operator
In .NET, and C# in particular, “await” is an operator just like ++ or &&. You can create all sorts of custom awaitable objects and build custom awaitable expressions.
Here is the simplest of examples!
Lets start by defining a task. A task needs to implement a single method:
- GetAwaiter()
- Returns an Awaiter. We will get to this next, its also got a schema to implement.
/// <summary>
/// A simple task.
/// </summary>
public class SimpleTask
{
/// <summary>
/// Gets the simple awaiter for the task.
/// </summary>
/// <returns>The awaiter.</returns>
public SimpleAwaiter GetAwaiter()
{
return new SimpleAwaiter();
}
}
Now for the Awaiter. The awaiter needs a few things defined:
- GetResult()
- Gets the result of the task.
- Can be a void or non-void method.
- IsCompleted
- A property which returns a value indicating whether a task has completed. Ours is synchronous, so this always returns true.
- ICriticalNotifyCompletion or INotifyCompletion
- OnCompleted(Action continuation)
- Called when returning from an async completion. If ICriticalNotifyCompletion is not implemented, then this will also be invoked on a synchronous completion.
- UnsafeOnCompleted(Action continuation)
- Only available if ICriticalNotifyCompletion is implemented, and will be invoked on a synchronous completion of the task. OnCompleted will not be called.
- OnCompleted(Action continuation)
using System;
using System.Runtime.CompilerServices;
public class SimpleAwaiter : ICriticalNotifyCompletion, INotifyCompletion
{
/// <summary>
/// Our task never runs async, so its always completed.
/// </summary>
public bool IsCompleted => true;
/// <summary>
/// Our task doesnt return anything, so this can be a void method,
/// but lets return something so we have something to await.
/// </summary>
public string GetResult() => "Hello World";
public void OnCompleted(Action continuation)
{
// OnCompleted is called on returning from an async completion.
throw new NotImplementedException();
}
public void UnsafeOnCompleted(Action continuation)
{
// UnsafeOnCompleted is called after a sync completion.
continuation();
}
}
Heres an example of how this can all work!
class Program
{
public static async Task Main(string[] args)
{
Console.WriteLine(await new SimpleTask());
}
}
Give it a shot! The result will be “Hello World” in the console.
A good place to check for more information is the C# language reference: await-expressions