TaskCompletionSource<T>.TrySetResult attempts to complete its associated Task<T> successfully, stores the supplied value as Result, and returns true only when it wins completion. A completed task transitions to RanToCompletion; later attempts return false rather than throwing. section 10.1 section 10.7
Use TrySetResult when completion may race with another outcome or callback:
- Expose tcs.Task to consumers while retaining completion control privately. section 10.1
- Call TrySetResult from a worker, event handler, or initialization routine after producing the value. section 10.1 section 10.3
- Prefer TrySetResult over SetResult when multiple threads or completion paths are possible; SetResult throws if the task is already complete. section 10.7
- Do not call it while holding a lock unless continuations are configured to run asynchronously, or move the call outside the lock. section 10.2
Adapting an event-based API
Create a TaskCompletionSource<int>, subscribe to the legacy completion event, and call tcs.TrySetResult(result) from the handler. Start the operation, return tcs.Task, and let callers await the result instead of managing the event directly. section 10.4
Listing 10.2 TaskCompletionSource.TrySetResult demo
public class TaskCompletionSourceDemo
{
private Task<int> BackgroundWork()
{
var tcs = new TaskCompletionSource<int>();
Task.Run(()=>
{
tcs.TrySetResult(7) #1
});
return tcs.Task;
}
public async Task RunDemo()
{
var result = await BackgroundWork(); #2
Console.WriteLine(result); #3
}
}
A minimal runnable pattern completes a TaskCompletionSource<int> on a worker and consumes its value with await. section 10.1
