liveBook · Manning

TaskCompletionSource<T>

As explained in C# Concurrency: Asynchronous and multithreaded programming

TaskCompletionSource<T> is a generic .NET class that provides a Task<T> whose completion and result can be controlled explicitly by application code.

TaskCompletionSource<T> creates one Task<T> whose completion is controlled explicitly by application code. Its Task starts in WaitingForActivation; awaiting it waits asynchronously until application code supplies a result, exception, or cancellation. section 10.0 section 10.1

Complete the task through the corresponding TrySet method:

  • TrySetResult(value) stores the value and completes the Task<T> successfully. section 10.1
  • TrySetException(exception) faults the task and makes the exception available through await. section 10.1
  • TrySetCanceled() completes the task as canceled; await, Wait, or Result then reports cancellation. section 10.7
  • Prefer TrySetResult, TrySetException, and TrySetCanceled over Set variants when multiple threads might race; TrySet methods return false if completion already occurred. section 10.7

The class bridges producer-side events and consumer-side await. Common applications include adapting callback or event APIs, exposing background initialization, and building asynchronous data structures. section 10.3 section 10.4 section 10.6

Wrapping an event-based operation

Create a TaskCompletionSource<int>, subscribe to CalculationComplete, call TrySetResult when the event supplies its value, start the operation, and return tcs.Task. Consumers can then await CallAsyncOperation(). section 10.4

Listing 10.5 Class with background initialization
public class RequiresInit
{
   private Task<int> _value;
 
   public RequiresInit ()
   {
      var tcs = new TaskCompletionSource<int>();
      _value = tcs.Task;                              #1
      Task.Run(()=>
      {
          try
          {
             Thread.Sleep(1000);                      #2
             tcs.TrySetResult(7);                     #3
          }
          catch(Exception ex)
          {
             tcs.TrySetException(ex);
          }
      });
   }
   public async Task<int> Add1()
   {
      var actualValue = await _value;                 #4
      return actualValue+1;
   }
}

A complete C# example combines background initialization, TrySetResult, TrySetException, and awaiting the shared Task from a later method. section 10.3

Continuation scheduling is a central safeguard. Completion may run code after await immediately inside TrySetResult, so do not complete while holding a lock unless the source was constructed with RunContinuationsAsynchronously; alternatively copy protected state and complete outside the lock. section 10.2 section 10.6

How C# Concurrency: Asynchronous and multithreaded programming covers it

How deep it goes
Explains task states, completion outcomes, continuation scheduling, locking hazards, and runnable implementation patterns.
Examples
Uses background initialization, event-based API adaptation, completion-state listings, and an asynchronous queue with cancellation.
What it assumes
Assumes familiarity with Task, async/await, callbacks, exceptions, cancellation tokens, and basic locking.
What you can do after
Apply it via C# to expose callback-driven work as awaitable tasks, propagate failures, support cancellation, and coordinate asynchronous producers and consumers.
How it connects
Connects Task<T> with async/await, callbacks, exceptions, cancellation, continuations, locks, and thread-safe asynchronous queues.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of C# Concurrency: Asynchronous and multithreaded programming. The section links point to the parts of the book it draws on.