The Problem ----------- Solution -------- There is a class [TaskCompletionSource<TResult>]( as described in [The Nature of TaskCompletionSource<TResult>]( The TaskCompletionSource<TResult> type serves two related purposes, both alluded to by its name: it is a source for creating a task, and the source for that task’s completion. In essence, a TaskCompletionSource<TResult> acts as the producer for a Task<TResult> and its completion. You create a TaskCompletionSource<TResult> and hand the underlying Task<TResult> it’s created, accessible from its Task property. Unlike Tasks created by Task.Factory.StartNew, the Task handed out by TaskCompletionSource<TResult> does not have any scheduled delegate associated with it [CancellationToken]( To me, a classic scenario for using TaskCompletionSource is when it's possible that my method won't necessarily have to do a time consuming operation. What it allows us to do is to choose the specific cases where we'd like to use a new thread. A good example for this is when you use a cache. You can have a GetResourceAsync method, which looks in the cache for the requested resource and returns at once (without using a new thread, by using TaskCompletionSource) if the resource was found. Only if the resource wasn't found, we'd like to use a new thread and retrieve it using Task.Run(). ``` using System.Threading; using System.Threading.Tasks; public class AsyncManualResetEvent { private TaskCompletionSource<bool> taskCompletionSource = new TaskCompletionSource<bool>(); public Task WaitAsync() { return taskCompletionSource.Task; } public void Set() { TaskCompletionSource<bool> tcs = taskCompletionSource; Task.Factory.StartNew(s => ((TaskCompletionSource<bool>) s).TrySetResult(true), tcs, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default); tcs.Task.Wait(); } public void Reset() { while (true) { TaskCompletionSource<bool> tcs = taskCompletionSource; if (!tcs.Task.IsCompleted || Interlocked.CompareExchange(ref taskCompletionSource, new TaskCompletionSource<bool>(), tcs) == tcs) { return; } } } } public static class TaskExtensions { public static Task AsAwaitable(this CancellationToken token) { var ev = new AsyncManualResetEvent(); token.Register(() => ev.Set()); return ev.WaitAsync(); } } ``` Source ------ * [How to await a CancellationToken]( by SocialEbola * [Building Async Coordination Primitives, Part 1: AsyncManualResetEvent]( by Stephen Toub * [Real life scenarios for using TaskCompletionSource<T>]( from StackOverflow * [Diving deep with WinRT and await]( by Stephen Toub from [Parallel Extensions Team](