Custom Awaiters & `INotifyCompletion` / `GetAwaiter()` Pattern
1Concept
C# async/await is pattern-based. Any type with a `GetAwaiter()` method returning an object with `IsCompleted`, `OnCompleted(Action)`, and `GetResult()` can be awaited with `await`.
2Architecture Diagram
Type with `public CustomAwaiter GetAwaiter()`
├── bool IsCompleted { get; }
├── void OnCompleted(Action continuation); (INotifyCompletion)
└── T GetResult();
│
▼ Enables `await customObject;` !3Code Example
C# 13 & .NET 9
using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
public struct CustomYieldAwaiter : INotifyCompletion
{
public bool IsCompleted => false;
public void OnCompleted(Action continuation) => Task.Run(continuation);
public void GetResult() { }
}
public class CustomAwaitable
{
public CustomYieldAwaiter GetAwaiter() => new();
}
public class CustomAwaiterDemo
{
public static async Task Main()
{
var custom = new CustomAwaitable();
await custom; // Pattern-based custom awaiter!
Console.WriteLine("Resumed from custom awaiter execution.");
}
}4Expected Output
Resumed from custom awaiter execution.
5Key Takeaways
- ✓C# await does not require inheriting from Task; it relies on the `GetAwaiter` pattern.
- ✓Powers unity game engine awaiters (`await new WaitForSeconds(1.0f)`).
- ✓Enables custom high-speed fiber and actor scheduling.