Skip to content

1. TASK — WHAT IT ACTUALLY IS

Definition

  • Task represents an operation that will complete in the future

  • It is NOT:

    • a thread

    • async by itself


Types

Task          // no result
Task<int>     // returns value

Internal Responsibilities

Task contains:
- completion state (Pending, Completed, Faulted)
- result (if Task<T>)
- exception (if any)
- list of continuations (callbacks)

Example — CPU Task

var task = Task.Run(() => 10);
ThreadPool thread executes work
Task completes when work finishes

Example — IO Task

var task = Task.Delay(1000);
No thread doing work
Timer → completes Task later

Interview Answer

A Task represents an asynchronous operation that may complete in the future. It encapsulates the state, result, and continuations of the operation, and may or may not involve a thread depending on whether the work is CPU-bound or I/O-bound.



2. async / await — WHAT THEY DO

Definition

  • async → enables use of await

  • await → pauses method until Task completes


Key Behavior

await does:
1. Check if Task is completed
2. If yes → continue synchronously
3. If no → register continuation + return

Internal Form

var awaiter = task.GetAwaiter();

if (!awaiter.IsCompleted)
{
    awaiter.OnCompleted(MoveNext);
    return;
}

awaiter.GetResult();

Example

async Task<int> Get()
{
    await Task.Delay(1000);
    return 10;
}

Interview Answer

Async/await enables non-blocking execution by splitting methods into state machines. When an await is encountered, execution is paused, and a continuation is registered to resume once the Task completes.



3. STATE MACHINE

Definition

  • Compiler converts async method into state machine

  • Stores:

    • current execution point

    • local variables

    • awaiter


Example Transformation

async Task<int> Get()
{
    await Task.Delay(1000);
    return 10;
}

Becomes conceptually

state = 0:
    start delay
    if not complete:
        save state = 1
        register continuation
        return

state = 1:
    resume
    return 10

Storage

State machine lives on heap
Task returned immediately

Interview Answer

Async methods are compiled into state machines that track execution state and resume execution after awaited operations complete.



4. STACK vs STATE MACHINE

Before await

Stack:

Level1
  ↓
Level2
  ↓
Level3

At await

State saved
Stack unwinds

After await

Stack: empty

Heap:
Level1StateMachine
Level2StateMachine
Level3StateMachine

Resume

ThreadPool thread:
    Level3.MoveNext()
        → Level2.MoveNext()
        → Level1.MoveNext()

Interview Answer

When an await is encountered, the call stack unwinds and execution state is stored in a heap-allocated state machine. Execution resumes later via continuations instead of stack frames.



5. YOUR CONFUSION POINT — “WHY LEVEL1 STOPS”

Code

async Task Level1()
{
    await Level2();
}

async Task Level2()
{
    await Level3();
}

async Task Level3()
{
    await Task.Delay(1000);
}

Execution

Step 1

Level1 calls Level2
Level2 calls Level3
Level3 calls Task.Delay

Step 2 — Level3 await

Task.Delay not completed
→ Level3 registers continuation
→ returns Task

Step 3 — Level2 await

Level3 Task not completed
→ Level2 registers continuation
→ returns Task

Step 4 — Level1 await

Level2 Task not completed
→ Level1 registers continuation
→ returns Task

Key Insight

await causes pause — not Task itself

Interview Answer

Each level awaits the Task returned by the next level. If the Task is incomplete, the method registers its continuation and returns, causing the call stack to unwind.



6. WHAT IS “SPECIAL” ABOUT Task.Delay

Definition

  • Returns a Task that is not completed initially

  • Completes later via timer


Behavior

Task.Delay:
    creates Task (IsCompleted = false)
    registers timer
    timer completes Task later

Comparison

await Task.FromResult(10);
IsCompleted = true → no pause

await Task.Delay(1000);
IsCompleted = false → pause

Key Insight

Async boundary = first incomplete Task

Interview Answer

Task.Delay represents a real asynchronous boundary because it returns an incomplete Task that is completed later by a timer, causing the awaiting method to pause.



7. CONTINUATIONS (CORE MECHANISM)

Definition

  • Continuation = method to run after Task completes

Registration

await Level3();

Level3.Task:
    continuations → Level2.MoveNext

Execution

Level3 completes →
    run Level2.MoveNext →
        Level2 completes →
            run Level1.MoveNext

Chain

Level3.Task → Level2 continuation
Level2.Task → Level1 continuation

Key Insight

No state machine calls another directly
All communication via Task

Interview Answer

Await registers a continuation on the awaited Task. When the Task completes, it invokes the continuation, resuming execution of the awaiting method.



8. THREAD USAGE

CPU-bound

await Task.Run(() => Work());
Thread actively executes work

IO-bound

await Task.Delay(1000);
No thread during wait
Timer completes Task

Resume

Continuation runs on ThreadPool thread

Interview Answer

Async does not guarantee new threads. CPU-bound tasks use ThreadPool threads, while I/O-bound tasks do not consume threads while waiting and resume via continuations.



9. SYNCHRONIZATION CONTEXT DEADLOCK

Code

GetDataAsync().Result;

Flow

Thread blocked
Continuation needs same thread
→ deadlock

Cause

await captures context
.Result blocks thread

Fix

await GetDataAsync();

Interview Answer

Deadlocks occur when a thread is blocked waiting for a Task, while the Task’s continuation requires that same thread due to SynchronizationContext capture.



10. FINAL MODEL

Task:
    holds completion + continuations

await:
    checks completion
    registers continuation if needed

state machine:
    stores execution state

thread:
    executes only when needed

FINAL INTERVIEW ANSWER

Async/await in C# is implemented using Tasks and compiler-generated state machines. When an await is encountered, the method checks if the Task is complete; if not, it registers a continuation and returns, unwinding the stack. The Task completes later, triggering the continuation and resuming execution. This model allows non-blocking execution and efficient use of threads.