The Problem ----------- Solution -------- There is a class [TaskCompletionSource<TResult>](https://msdn.microsoft.com/en-us/library/dd449174.aspx) as described in [The Nature of TaskCompletionSource<TResult>](http://blogs.msdn.com/b/pfxteam/archive/2009/06/02/9685804.aspx): 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](https://msdn.microsoft.com/en-us/library/system.threading.cancellationtoken.aspx) 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](https://socialeboladev.wordpress.com/2013/03/05/how-to-await-a-cancellationtoken/) by SocialEbola * [Building Async Coordination Primitives, Part 1: AsyncManualResetEvent](http://blogs.msdn.com/b/pfxteam/archive/2012/02/11/10266920.aspx) by Stephen Toub * [Real life scenarios for using TaskCompletionSource<T>](http://stackoverflow.com/questions/15316613/real-life-scenarios-for-using-taskcompletionsourcet) from StackOverflow * [Diving deep with WinRT and await](http://blogs.msdn.com/b/windowsappdev/archive/2012/04/24/diving-deep-with-winrt-and-await.aspx) by Stephen Toub from [Parallel Extensions Team](http://blogs.msdn.com/b/pfxteam/)