In this lesson, you will learn how to take total control over how asynchronous methods execute by creating your own "engine" for async tasks.
The Problem: One Size Doesn't Fit All
Normally, when you mark a method as async, C# uses the standard AsyncTaskMethodBuilder under the hood. This builder knows how to create Task or ValueTask objects and manage their state machines. However, if you are building a high-performance system—like a game engine or a custom networking framework—you might not want the overhead of allocating standard Task objects. You might want to run tasks on a specialized thread pool or use a custom data structure to track completion.
The Solution: Custom Builders
A Custom Async Method Builder is a class that tells the compiler: "Don't use the default task machinery; use my logic instead."
You instruct the compiler to use your custom builder by applying the [AsyncMethodBuilder(typeof(MyCustomBuilder))] attribute to your custom return type (like a custom MyCustomTask struct). Once you do this, the C# compiler intercepts the async state machine and routes all its operations—like AwaitOnCompleted or SetResult—through your builder.
A Conceptual Sketch
Think of the default builder as a standard delivery truck. A custom builder is you building your own bicycle to deliver the package instead, perhaps because it's faster or fits down a narrower alley.
[AsyncMethodBuilder(typeof(MyCustomBuilder))]
public struct MyCustomTask { /* ... */ }
public struct MyCustomBuilder
{
// The compiler calls these methods to drive the state machine
public static MyCustomBuilder Create() => new MyCustomBuilder();
public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { /* ... */ }
public void SetResult() { /* Custom logic to complete the task */ }
public void SetException(Exception e) { /* Custom error handling */ }
// ... plus methods for awaiter integration
}
By implementing this builder, you control exactly when the state machine transitions, how memory is allocated for the task, and how execution is scheduled. This is a powerful, low-level tool that allows you to strip away the abstractions of standard Task objects for specific, high-performance environments.
Key Takeaway: A custom async method builder allows you to replace the standard C# task-handling logic with your own implementation, giving you complete authority over the execution, scheduling, and memory allocation of asynchronous methods.