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
