{"id":56061,"date":"2011-01-13T22:33:00","date_gmt":"2011-01-13T22:33:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/pfxteam\/2011\/01\/13\/await-anything\/"},"modified":"2011-01-13T22:33:00","modified_gmt":"2011-01-13T22:33:00","slug":"await-anything","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/await-anything\/","title":{"rendered":"await anything;"},"content":{"rendered":"<p>One of the very cool things about the new <a href=\"https:\/\/msdn.com\/vstudio\/async\">await<\/a> keyword in C# and Visual Basic is that it&rsquo;s pattern based.&nbsp; It works great with Task and Task&lt;TResult&gt;, and awaiting those two types will represent the vast majority of uses, but they&rsquo;re by no means the only types that can be awaited.&nbsp; The languages support awaiting any instance that exposes the right method (either instance method or extension method): GetAwaiter.&nbsp; A GetAwaiter needs to implement the INotifyCompletion interface (and optionally the ICriticalNotifyCompletion interface) and&nbsp;return a type that itself exposes three members:<\/p>\n<blockquote>\n<p><span style=\"font-family: Consolas\">bool IsCompleted { get; }<br>void OnCompleted(Action continuation);<br>TResult GetResult(); \/\/ TResult can also be void<\/span><\/p>\n<\/blockquote>\n<p>As an example of this, Task&rsquo;s GetAwaiter method returns a value of type TaskAwaiter:<\/p>\n<blockquote>\n<p><span style=\"font-family: Consolas\">public struct TaskAwaiter : ICriticalNotifyCompletion<\/span><\/p>\n<\/blockquote>\n<p>and that&rsquo;s what enables awaiting the Task.&nbsp; This is a simplification, but in short the OnCompleted method registers the Action as a continuation onto the Task (e.g. with ContinueWith), such that when the task completes, it will cause the compiler-generated state machine around the await to pick back up where it left off.<\/p>\n<p>The title of this post is &ldquo;await anything;&rdquo;, so let&rsquo;s see how we can await things besides Task and Task&lt;TResult&gt;.&nbsp; To do that, we&rsquo;ll need appropriate &ldquo;awaiter&rdquo; types for the &ldquo;awaitable&rdquo; type to await.&nbsp; That doesn&rsquo;t mean we have to write new &ldquo;awaiter&rdquo; types, however.&nbsp; There are really two different approaches to making something awaitable: develop a new awaiter type that exposes the right pattern, or figure out how to create a Task or Task&lt;TResult&gt; from the thing being awaited, and then just reuse Task or Task&lt;TResult&gt;&rsquo;s awaiter.&nbsp; For the majority of cases, the latter approach is very straightforward, so we&rsquo;ll start with that.<\/p>\n<p>Let&rsquo;s say you want to be able to write code like:<\/p>\n<blockquote>\n<p><span style=\"font-family: Consolas\">await TimeSpan.FromMinutes(15);<\/span><\/p>\n<\/blockquote>\n<p>in order to asynchronously pause for 15 minutes.&nbsp; To do that, we can develop a 1-line GetAwaiter method for TimeSpan:<\/p>\n<blockquote>\n<p><span style=\"font-family: Consolas\">public static TaskAwaiter GetAwaiter(this TimeSpan timeSpan) <br>{ <br>&nbsp;&nbsp;&nbsp; return TaskEx.Delay(timeSpan).GetAwaiter(); <br>}<\/span><\/p>\n<\/blockquote>\n<p>That&rsquo;s it.&nbsp; Or let&rsquo;s say we like waiting for periods of time so much, that we want to simply this down to just:<\/p>\n<blockquote>\n<p><span style=\"font-family: Consolas\">await 15000; \/\/ in milliseconds<\/span><\/p>\n<\/blockquote>\n<p>No problem, we can do that with another one-line awaiter:<\/p>\n<blockquote>\n<p><span style=\"font-family: Consolas\">public static TaskAwaiter GetAwaiter(this Int32 millisecondsDue) <br>{ <br>&nbsp;&nbsp;&nbsp; return TimeSpan.FromMilliseconds(millisecondsDue).GetAwaiter(); <br>}<\/span><\/p>\n<\/blockquote>\n<p>Let&rsquo;s say we like waiting for time-like things so much that we want to be able to wait until a particular date\/time, ala<\/p>\n<blockquote>\n<p><span style=\"font-family: Consolas\">await DateTimeOffset.UtcNow.AddMinutes(1);<\/span><\/p>\n<\/blockquote>\n<p>Again, piece of cake:<\/p>\n<blockquote>\n<p><span style=\"font-family: Consolas\">public static TaskAwaiter GetAwaiter(this DateTimeOffset dateTimeOffset) <br>{ <br>&nbsp;&nbsp;&nbsp; return (dateTimeOffset &#8211; DateTimeOffset.UtcNow).GetAwaiter(); <br>}<\/span><\/p>\n<\/blockquote>\n<p>Tired of time?&nbsp; Alright.&nbsp; The GetAwaiter function for Task allows you to wait for a single task, how about enabling waiting for an enumerable of tasks so that you can write code like:<\/p>\n<blockquote>\n<p><span style=\"font-family: Consolas\">await from url in urls select DownloadAsync(url);<\/span><\/p>\n<\/blockquote>\n<p>Easy peasy:<\/p>\n<blockquote>\n<p><span style=\"font-family: Consolas\">public static TaskAwaiter GetAwaiter(this IEnumerable&lt;Task&gt; tasks) <br>{ <br>&nbsp;&nbsp;&nbsp; return TaskEx.WhenAll(tasks).GetAwaiter(); <br>}<\/span><\/p>\n<\/blockquote>\n<p>All of the examples thus far were one-liners because we already have a function that takes the input to the extension method and produces a task from it.&nbsp; However, with just a few more lines, you can convert almost anything that has some notion of future completion into a task, through the TaskCompletionSource&lt;TResult&gt; type.&nbsp; If you can express your need by completing the statement &ldquo;I want to await until &hellip;&rdquo; or &ldquo;I want the await to complete when &hellip;&rdquo;, this is likely a good approach for you.<\/p>\n<p>As an example, consider wanting to spin up another process and then asynchronously wait for that process to complete, e.g.<\/p>\n<blockquote>\n<p><span style=\"font-family: Consolas\">await Process.Start(&ldquo;Foo.exe&rdquo;);<\/span><\/p>\n<\/blockquote>\n<p>You could do that with a GetAwaiter method like the following:<\/p>\n<blockquote>\n<p><span style=\"font-family: Consolas\">public static TaskAwaiter&lt;int&gt; GetAwaiter(this Process process) <br>{ <br>&nbsp;&nbsp;&nbsp; var tcs = new TaskCompletionSource&lt;int&gt;(); <br>&nbsp;&nbsp;&nbsp; process.EnableRaisingEvents = true; <br>&nbsp;&nbsp;&nbsp; process.Exited += (s, e) =&gt; tcs.TrySetResult(process.ExitCode); <br>&nbsp;&nbsp;&nbsp; if (process.HasExited) tcs.TrySetResult(process.ExitCode); <br>&nbsp;&nbsp;&nbsp; return tcs.Task.GetAwaiter(); <br>}<\/span><\/p>\n<\/blockquote>\n<p>Or maybe you want to asynchronously wait until cancellation is requested, e.g.<\/p>\n<blockquote>\n<p><span style=\"font-family: Consolas\">await cancellationToken;<\/span><\/p>\n<\/blockquote>\n<p>That could be done with a GetAwaiter like the following:<\/p>\n<blockquote>\n<p><span style=\"font-family: Consolas\">public static TaskAwaiter GetAwaiter(this CancellationToken cancellationToken) <br>{ <br>&nbsp;&nbsp;&nbsp; var tcs = new TaskCompletionSource&lt;bool&gt;(); <br>&nbsp;&nbsp;&nbsp; Task t = tcs.Task; <br>&nbsp;&nbsp;&nbsp; if (cancellationToken.IsCancellationRequested) tcs.SetResult(true); <br>&nbsp;&nbsp;&nbsp; else cancellationToken.Register(s =&gt; ((TaskCompletionSource&lt;bool&gt;)s).SetResult(true), tcs); <br>&nbsp;&nbsp;&nbsp; return t.GetAwaiter(); <br>}<\/span><\/p>\n<\/blockquote>\n<p>You get the idea.<\/p>\n<p>The second approach to making an awaitable type is to implement a custom awaiter.&nbsp; This could either be a separate type that&rsquo;s returned by GetAwaiter and that exposes the IsCompleted\/OnCompleted\/GetResult members, or it could be a GetAwaiter method that returns &ldquo;this&rdquo;, with IsCompleted\/OnCompleted\/GetResult also exposed on the awaitable type.&nbsp; You&rsquo;d typically go this route if you can&rsquo;t express your desire as &ldquo;I want the await to complete when&hellip;&rdquo;, but rather as &ldquo;When the await completes, I want to continue executing &hellip;&rdquo;, filling in the blank for that &ldquo;&hellip;&rdquo;.&nbsp; In particular, you&rsquo;d need to use this approach if you need full control over how (rather than when) the &ldquo;Action continuation&rdquo; delegate is invoked.<\/p>\n<p>Imagine, for example, that you wanted to launch some work to run on the ThreadPool.&nbsp; This work would compute a string and then store the result into a control on your UI.&nbsp; To modify the control, you need to be on the UI thread, so you somehow need to transition to the UI thread to do that work.&nbsp; If this were, for example, a Windows Forms application, we could accomplish this by building an awaiter for a Windows Forms Control.&nbsp; That would allow us to write code like:<\/p>\n<blockquote>\n<p><span style=\"font-family: Consolas\">ThreadPool.QueueUserWorkItem(async delegate <br>{ <br>&nbsp;&nbsp;&nbsp; string text = ComputeString(); <br>&nbsp;&nbsp;&nbsp; await button1; <br>&nbsp;&nbsp;&nbsp; button1.Text = text; <br>});<\/span><\/p>\n<\/blockquote>\n<p>We want the operation of awaiting the button1 to transition to the UI thread and then continue the execution there.&nbsp; We can do that with an implementation like the following:<\/p>\n<blockquote>\n<p><span style=\"font-family: Consolas\">public static ControlAwaiter GetAwaiter(this Control control) <br>{ <br>&nbsp;&nbsp;&nbsp; return new ControlAwaiter(control); <br>}<\/span><\/p>\n<p><span style=\"font-family: Consolas\">public struct ControlAwaiter : INotifyCompletion<br>{ <br>&nbsp;&nbsp;&nbsp; private readonly Control m_control;<\/span><\/p>\n<p><span style=\"font-family: Consolas\">&nbsp;&nbsp;&nbsp; public ControlAwaiter(Control control) <br>&nbsp;&nbsp;&nbsp; {&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_control = control; <br>&nbsp;&nbsp;&nbsp; }<\/p>\n<p>&nbsp;&nbsp;&nbsp; public bool IsCompleted <br>&nbsp;&nbsp;&nbsp; {&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; get { return !m_control.InvokeRequired; } <br>&nbsp;&nbsp;&nbsp; }<\/span><\/p>\n<p><span style=\"font-family: Consolas\">&nbsp;&nbsp;&nbsp; public void OnCompleted(Action continuation) <br>&nbsp;&nbsp;&nbsp; {&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_control.BeginInvoke(continuation);&nbsp;<br>&nbsp;&nbsp;&nbsp; }<\/span><\/p>\n<p><span style=\"font-family: Consolas\">&nbsp;&nbsp;&nbsp; public void GetResult() { } <br>}<\/span><\/p>\n<\/blockquote>\n<p>You can also combine these approaches, such as by writing a custom awaiter which wraps the awaiter for a task, layering on additional functionality.&nbsp; For example, culture information is not flowed by default as part of ExecutionContext, which is the standard .NET mechanism for transferring important environmental information across asynchronous invocations.&nbsp; What if we wanted to make it easy to flow culture?&nbsp; Imagine the following syntax for awaiting a task with the flow of culture:<\/p>\n<blockquote>\n<p>await task.WithCulture();<\/p>\n<\/blockquote>\n<p>We could enable that with code like the following:<\/p>\n<blockquote>\n<p><span style=\"font-family: Consolas\">public static CultureAwaiter WithCurrentCulture(this Task task) <br>{ <br>&nbsp;&nbsp;&nbsp; return new CultureAwaiter(task); <br>}<\/span><\/p>\n<p><span style=\"font-family: Consolas\">public class CultureAwaiter : INotifyCompletion<br>{ <br>&nbsp;&nbsp;&nbsp; private readonly TaskAwaiter m_awaiter; <br>&nbsp;&nbsp;&nbsp; private CultureInfo m_culture;<\/span><\/p>\n<p><span style=\"font-family: Consolas\">&nbsp;&nbsp;&nbsp; public CultureAwaiter(Task task) <br>&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (task == null) throw new ArgumentNullException(&#8220;task&#8221;); <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_awaiter = task.GetAwaiter(); <br>&nbsp;&nbsp;&nbsp; }<\/span><\/p>\n<p><span style=\"font-family: Consolas\">&nbsp;&nbsp;&nbsp; public CultureAwaiter GetAwaiter() { return this; }<\/p>\n<p>&nbsp;&nbsp;&nbsp; public bool IsCompleted { get { return m_awaiter.IsCompleted; } }<\/span><\/p>\n<p><span style=\"font-family: Consolas\">&nbsp;&nbsp;&nbsp; public void OnCompleted(Action continuation) <br>&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_culture = Thread.CurrentThread.CurentCulture;<\/span><span style=\"font-family: Consolas\">&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_awaiter.OnCompleted(continuation); <br>&nbsp;&nbsp;&nbsp; }<\/span><\/p>\n<p><span style=\"font-family: Consolas\">&nbsp;&nbsp;&nbsp; public void GetResult() <br>&nbsp;&nbsp;&nbsp; { <br>&nbsp; &nbsp; &nbsp; &nbsp; if (m_culture != null)&nbsp;<\/span><span style=\"font-family: Consolas\">Thread.CurrentThread.CurrentCulture = m_culture;&nbsp;<\/span><\/p>\n<p><span style=\"font-family: Consolas\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_awaiter.GetResult(); <br>&nbsp;&nbsp;&nbsp; } <br>}<\/span><\/p>\n<\/blockquote>\n<p>This awaiter implementation wraps a TaskAwaiter, and this implementation&#8217;s IsCompleted, OnCompleted, and GetResult members delegate to the contained TaskAwaiter&rsquo;s.&nbsp; On top of that, though, the implementation captures the current culture in OnCompleted and then restores it in GetResult.<\/p>\n<p>By now, it should be obvious that there are loads of interesting possibilities here.&nbsp; I look forward to seeing all the interesting and useful awaiters you come up with.&nbsp; Just keep in mind that while there are plenty of &ldquo;cool&rdquo; things you can do, code readability and maintainability is really important, so make sure that the coolness isn&rsquo;t trumped by lack of clarity about the code&rsquo;s meaning.<\/p>\n<p><em>[NOTE 4\/09\/2012: This blog post was originally based on the original Async CTP released in Oct 2010.&nbsp; Visual Studio 11 Beta released in Feb 2012 uses an updated awaiter pattern, and this post has now been updated to conform to that pattern.]<\/em><\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>One of the very cool things about the new await keyword in C# and Visual Basic is that it&rsquo;s pattern based.&nbsp; It works great with Task and Task&lt;TResult&gt;, and awaiting those two types will represent the vast majority of uses, but they&rsquo;re by no means the only types that can be awaited.&nbsp; The languages support [&hellip;]<\/p>\n","protected":false},"author":360,"featured_media":58792,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[7908],"tags":[36,7909,7912],"class_list":["post-56061","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-pfxteam","tag-async","tag-parallel-extensions","tag-task-parallel-library"],"acf":[],"blog_post_summary":"<p>One of the very cool things about the new await keyword in C# and Visual Basic is that it&rsquo;s pattern based.&nbsp; It works great with Task and Task&lt;TResult&gt;, and awaiting those two types will represent the vast majority of uses, but they&rsquo;re by no means the only types that can be awaited.&nbsp; The languages support [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/56061","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/360"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=56061"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/56061\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/58792"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=56061"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=56061"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=56061"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}