1 / 78

“a language+framework push for compositional asynchrony” Async.NET Working Group, F#, Axum, Task<T>

“a language+framework push for compositional asynchrony” Async.NET Working Group, F#, Axum, Task<T> Avner Aharoni, Mads Torgersen, Stephen Toub, Alex Turner, Lucian Wischik. “a language+framework push for compositional asynchrony”. Concurrency

keiji
Download Presentation

“a language+framework push for compositional asynchrony” Async.NET Working Group, F#, Axum, Task<T>

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. “a language+framework push for compositional asynchrony” Async.NET Working Group, F#, Axum, Task<T> Avner Aharoni, Mads Torgersen, Stephen Toub, Alex Turner, Lucian Wischik

  2. “a language+framework push for compositional asynchrony” • Concurrency • is about running or appearing to run two things at once, through cooperative or pre-emptive multitasking or multicore. • Good reasons to use concurrency: • for the CPU-bound multicore computational kernel (e.g. codecs); • for a server handling requests from different processes/machines; • to “bet on more than one horse” and use whichever was fastest. • Asynchrony • is about results that are delayed, and yielding control while awaiting them(co-operative multitasking). • Good reasons to use asynchrony: • for overall control / coordination structure of a program; • for UI responsiveness; • for IO- and network-bound code; • for coordinating your CPU-bound multicore computational kernel.

  3. “a language+framework push for compositional asynchrony” • Concurrency • is about running or appearing to run two things at once, through cooperative or pre-emptive multitasking or multicore. • Good reasons to use concurrency: • for the CPU-bound multicore computational kernel (e.g. codecs); • for a server handling requests from different processes/machines; • to “bet on more than one horse” and use whichever was fastest. • Asynchrony • is about results that are delayed, and yielding control while awaiting them(co-operative multitasking). • Good reasons to use asynchrony: • for overall control / coordination structure of a program; • for UI responsiveness; • for IO- and network-bound code; • for coordinating your CPU-bound multicore computational kernel. • Bad reasons to use concurrency: • “You should stick IO on a background thread to avoid blocking the UI” • “Asynchrony makes your program structure too complex”

  4. The following is wrong. Can you spot the flaw? “A waiter’s job is to wait on a table until the patrons have finished their meal.If you want to serve two tables concurrently, you must hire two waiters.”

  5. The following is from the Android developer blog. Can you spot the flaw?“A good practice in creating responsive applications is to make sure your main UI thread does the minimum amount of work. Any potentially long task that may hang your application should be handled in a different thread. Typical examples of such tasks are network operations, which involve unpredictable delays.”

  6. “a language+framework push for compositional asynchrony” Outline Of Talk 1. Demoof simple end-user experience with CTP. Threading story. 2. Language specification of “await” keyword through compiler rewrites. 3. Frameworkthe new “Task Asynchronous Pattern”; combinators; ecosystem 4. Designhot vs cold; async blocks vs methods; IAsyncEnumerable<T> 5. Theorythe academic theory around async – callcc? co-monads? 1. Demo/th 2. Language 3. Framework 4. Design 5. Theory

  7. “a language+framework push for compositional asynchrony” demo 1. Demo/th 2. Language 3. Framework 4. Design 5. Theory

  8. This is a very simple WPF application. When you click the button,it retrieves the top Digg news story and its most recent comment. My task: port it to Silverlight

  9. [1/10] This is the original WPF code. Sub Button1_Click(sender As Object, e As RoutedEventArgs) Handles Button1.Click Try Dim story = GetDiggStory() textBox1.Text = story.Description textBox2.Text = GetDiggComment(story.Id)Catch ex AsException textBox1.Text = ex.ToStringEnd Try End Sub Function GetDiggStory() AsDiggStory Dim web As NewWebClient Dim rss = web.DownloadString(newUri("http://api.digg.com/?search&count=1&query=news"))Dim story = XElement.Parse(rss).<story> ReturnNewDiggStoryWith { .Description=story.<description>.Value, .Id=story.@id.Value } End Function FunctionGetDiggComment() AsString Dim web As NewWebClient Dim rss = web.DownloadString(newUri("http://api.digg.com/?getComments&count=1&id=" & id))ReturnXElement.Parse(rss).<comment>.ValueEnd Function ClassDiggStory Public Id As String Public Description As String End Class

  10. [1/10] If you try to compile it on Silverlight, it doesn’t work. That’s because Silverlight lacks “DownloadString” API. “DownloadString” is synchronous – it blocks the UI, making it non-responsive. Silverlight chose not to have it, because it’s bad to block the UI of the web-browser. Sub Button1_Click(sender As Object, e As RoutedEventArgs) Handles Button1.Click Try Dim story = GetDiggStory() textBox1.Text = story.Description textBox2.Text = GetDiggComment(story.Id)Catch ex AsException textBox1.Text = ex.ToStringEnd Try End Sub Function GetDiggStory() AsDiggStory Dim web As NewWebClient Dim rss = web.DownloadString(NewUri("http://api.digg.com/?search&count=1&query=news"))Dim story = XElement.Parse(rss).<story> ReturnNewDiggStoryWith { .Description=story.<description>.Value, .Id=story.@id.Value } End Function FunctionGetDiggComment() AsString Dim web As NewWebClient Dim rss = web.DownloadString(NewUri("http://api.digg.com/?getComments&count=1&id=" & id))ReturnXElement.Parse(rss).<comment>.ValueEnd Function ClassDiggStory Public Id As String Public Description As String End Class

  11. “a language+framework push for compositional asynchrony” It was hard to make this code asynchronous before Async...

  12. [2/10] [2/10] Problem: DownloadString doesn’t exist Function GetDiggStory() AsDiggStory Dim web As NewWebClient Dim rss = web.DownloadString(NewUri("http://api.digg.com/?search&count=1&query=news"))Dim story = XElement.Parse(rss).<story>Return NewDiggStoryWith { .Desc=story.<description>.Value, .Id=story.@id.Value } End Function ClassDiggStory Public Id As String Public Description As String End Class

  13. [2/10] Solution: use DownloadStringAsync instead (which merely initiates the web-request). And add an event-handler for when the server eventually comes back with a response. Function GetDiggStory() AsDiggStory Dim web As NewWebClient AddHandler web.DownloadStringCompleted,Sub(_, e) Dim rss = e.ResultDim story = XElement.Parse(rss).<story>Return NewDiggStoryWith { .Desc=story.<description>.Value, .Id=story.@id.Value } End Sub web.DownloadStringAsync(NewUri("http://api.digg.com/?search&count=1&query=news")) End Function ClassDiggStory Public Id As String Public Description As String End Class

  14. [3/10] Problem: now the “Return” statement doesn’t work. That’s because it now returns from the inner Sub, not the outer function. “Callbacks/events do not compose with the Return statement.” Function GetDiggStory() AsDiggStory Dim web As NewWebClient AddHandler web.DownloadStringCompleted,Sub(_, e) Dim rss = e.ResultDim story = XElement.Parse(rss).<story>Return NewDiggStoryWith { .Desc=story.<description>.Value, .Id=story.@id.Value } End Sub web.DownloadStringAsync(NewUri("http://api.digg.com/?search&count=1&query=news")) End Function ClassDiggStory Public Id As String Public Description As String End Class

  15. [3/10] Solution: deliver back the result of GetDiggStory through a callback of our own. Sub GetDiggStory(Callback AsAction(OfDiggStory)) Dim web As NewWebClient AddHandler web.DownloadStringCompleted,Sub(_, e) Dimrss = e.ResultDim story = XElement.Parse(rss).<story>Callback(NewDiggStoryWith { .Desc=story.<description>.Value, .Id=story.@id.Value }) End Sub web.DownloadStringAsync(NewUri("http://api.digg.com/?search&count=1&query=news")) End Sub ClassDiggStory Public Id As String Public Description As String End Class

  16. [4/10] Problem: we’re not handling the asynchronous error case. * DownloadStringAsync might give an exception immediately if it’s unable to make the request. * Or, if the server responds with an HTTP error code, then we’ll get the exception back in our handler. Sub GetDiggStory(Callback AsAction(OfDiggStory)) Dim web As NewWebClient AddHandler web.DownloadStringCompleted,Sub(_, e) ... e.Error... Dimrss = e.ResultDim story = XElement.Parse(rss).<story>Callback(NewDiggStoryWith { .Desc=story.<description>.Value, .Id=story.@id.Value }) End Sub web.DownloadStringAsync(NewUri("http://api.digg.com/?search&count=1&query=news")) End Sub ClassDiggStory Public Id As String Public Description As String End Class

  17. [4/10] Solution: give back error information in two places: either from the exception of DownloadStringAsync, or in our callback, depending on where the error came from. “Callbacks/events do not compose with the throwing of exceptions.” Sub GetDiggStory(Callback AsAction(OfDiggStory)) Dim web As NewWebClient AddHandler web.DownloadStringCompleted,Sub(_, e) If e.Error IsNot Nothing Then Callback(NewDiggStoryWith { .Error=e.Error }) : Return Dimrss = e.ResultDim story = XElement.Parse(rss).<story>Callback(NewDiggStoryWith { .Desc=story.<description>.Value, .Id=story.@id.Value }) End Sub web.DownloadStringAsync(NewUri("http://api.digg.com/?search&count=1&query=news")) End Sub ClassDiggStory Public Id As String Public Description As String Public Error As Exception End Class

  18. [5/10] Problem: now we have to update Button1_Click, since it invokes functions that now take callbacks. Sub Button1_Click(sender As Object, e As RoutedEventArgs) Handles Button1.Click Try Dim story = GetDiggStory() textBox1.Text = story.Description textBox2.Text = GetDiggComments(story.Id) Catch ex AsException textBox1.Text = ex.ToStringEnd Try End Sub

  19. [5/10] Solution: instead of using semicolon (C#) or linebreak (VB) to separate one statement from the next, we have to use a nested lambda. “Callbacks/events do not compose with the semicolon operator.” Sub Button1_Click(sender As Object, e As RoutedEventArgs) Handles Button1.Click Try GetDiggStory( Sub(story) textBox1.Text = story.Description GetDiggComment(story.Id, Sub(comment) textBox2.Text = comment End Sub) End Sub) Catch ex AsException textBox1.Text = ex.ToStringEnd Try End Sub

  20. [6/10] Problem: we have to fix up error-handling as well, since errors might come either through an exception or through the callback. “Callbacks/events do not compose with exception handling.” (nor with Using, nor with For/While loops) Sub Button1_Click(sender As Object, e As RoutedEventArgs) Handles Button1.Click Try GetDiggStory( Sub(story) ... story.Error... textBox1.Text = story.Description GetDiggComment(story.Id, Sub(comment) ... ?error?... textBox2.Text = comment End Sub) End Sub) Catch ex AsException textBox1.Text = ex.ToStringEnd Try End Sub

  21. [6/10] Solution: use explicit error checks in addition to the exception handling. The code basically has to be duplicated. Sub Button1_Click(sender As Object, e As RoutedEventArgs) Handles Button1.Click Try GetDiggStory( Sub(story) If story.Error IsNot Nothing Then textBox1.Text = story.Error.ToString : Return textBox1.Text = story.Description GetDiggComment(story.Id, Sub(comment) ... ?maybe return a structure instead of just a string?... textBox2.Text = comment End Sub) End Sub) Catch ex AsException textBox1.Text = ex.ToStringEnd Try End Sub

  22. “a language+framework push for compositional asynchrony” The Async CTP offers a better way to make this code asynchronous.

  23. [7/10] Problem: these methods need to be made asynchronous. Sub Button1_Click(sender As Object, e As RoutedEventArgs) Handles Button1.Click Try Dim story = GetDiggStory() textBox1.Text = story.Description textBox2.Text = GetDiggComment(story.Id)Catch ex AsException textBox1.Text = ex.ToStringEnd Try End Sub Function GetDiggStory() AsDiggStory Dim web As NewWebClient Dim rss = web.DownloadString(NewUri("http://api.digg.com/?search&count=1&query=news"))Dim story = XElement.Parse(rss).<story> ReturnNewDiggStoryWith { .Description=story.<description>.Value, .Id=story.@id.Value } End Function FunctionGetDiggComment() AsString Dim web As NewWebClient Dim rss = web.DownloadString(NewUri("http://api.digg.com/?getComments&count=1&id=" & id))ReturnXElement.Parse(rss).<comment>.ValueEnd Function ClassDiggStory Public Id As String Public Description As String End Class

  24. [8/10] Solution part 1: Mark these methods as “Async” and change their return types to Task(Of ...). By convention, all async methods in the framework have names ending in “Async”. Sub Button1_Click(sender As Object, e As RoutedEventArgs) Handles Button1.Click Try Dim story = GetDiggStory() textBox1.Text = story.Description textBox2.Text = GetDiggComment(story.Id)Catch ex AsException textBox1.Text = ex.ToStringEnd Try End Sub Async Function GetDiggStoryAsync() AsTask(OfDiggStory) Dim web As NewWebClient Dim rss = web.DownloadString(NewUri("http://api.digg.com/?search&count=1&query=news"))Dim story = XElement.Parse(rss).<story> ReturnNewDiggStoryWith { .Description=story.<description>.Value, .Id=story.@id.Value } End Function Async Function GetDiggCommentAsync() AsTask(OfString) Dim web As NewWebClient Dim rss = web.DownloadString(NewUri("http://api.digg.com/?getComments&count=1&id=" & id))ReturnXElement.Parse(rss).<comment>.ValueEnd Function ClassDiggStory Public Id As String Public Description As String End Class

  25. [9/10] Solution part 2: “Await” the Task-Asynchronous versions of all calls, instead of invoking the synchronous versions. Sub Button1_Click(sender As Object, e As RoutedEventArgs) Handles Button1.Click Try Dim story = AwaitGetDiggStoryAsync() textBox1.Text = story.Description textBox2.Text = AwaitGetDiggCommentAsync(story.Id)Catch ex AsException textBox1.Text = ex.ToStringEnd Try End Sub Async Function GetDiggStoryAsync() AsTask(OfDiggStory) Dim web As NewWebClient Dim rss = Awaitweb.DownloadStringTaskAsync(NewUri("http://api.digg.com/?search&count=1&query=news"))Dim story = XElement.Parse(rss).<story> ReturnNewDiggStoryWith { .Description=story.<description>.Value, .Id=story.@id.Value } End Function Async Function GetDiggCommentAsync() AsTask(OfString) Dim web As NewWebClient Dim rss = Awaitweb.DownloadStringTaskAsync(NewUri("http://api.digg.com/?getComments&count=1&id=" & id))ReturnXElement.Parse(rss).<comment>.ValueEnd Function ClassDiggStory Public Id As String Public Description As String End Class

  26. [10/10] Solution part 3: Because Button1_Click has an “Await” in it, it too must be marked Async. (The Async modifier has to “bubble-up” the call hierarchy.) AsyncSub Button1_Click(sender As Object, e As RoutedEventArgs) Handles Button1.Click Try Dim story = Await GetDiggStoryAsync() textBox1.Text = story.Description textBox2.Text = Await GetDiggCommentAsync(story.Id)Catch ex AsException textBox1.Text = ex.ToStringEnd Try End Sub Async Function GetDiggStoryAsync() AsTask(OfDiggStory) Dim web As NewWebClient Dim rss = Await web.DownloadStringTaskAsync(NewUri("http://api.digg.com/?search&count=1&query=news"))Dim story = XElement.Parse(rss).<story> ReturnNewDiggStoryWith { .Description=story.<description>.Value, .Id=story.@id.Value } End Function Async Function GetDiggCommentAsync() AsTask(OfString) Dim web As NewWebClient Dim rss = Await web.DownloadStringTaskAsync(NewUri("http://api.digg.com/?getComments&c=1&id=" & id))ReturnXElement.Parse(rss).<comment>.ValueEnd Function ClassDiggStory Public Id As String Public Description As String End Class

  27. My task: port it to Silverlight Status: finished ahead of schedule! I think I’ll go home early today.

  28. How the demo actually worked UIthread IOCP thread async voidbutton1_Click() {vardiggTask= GetDiggAsync(); vardigg= awaitdiggTask; textBox1.Text = digg; } async Task<string> GetDiggAsync() {varweb = newWebClient(); vardownTask = web.DownTaskAsync("http://digg.com"); varrss= awaitdownTask; vardigg = XElement.Parse(rss).<story>.<description>; returndigg; } 1. Demo/th 2. Language 3. Framework 4. Design 5. Theory

  29. [1/12] A button-click arrives on the UI queue UIthread IOCP thread async voidbutton1_Click() {vardiggTask= GetDiggAsync(); vardigg= awaitdiggTask; textBox1.Text = digg; } async Task<string> GetDiggAsync() {varweb = newWebClient(); vardownTask = web.DownTaskAsync("http://digg.com"); varrss= awaitdownTask; vardigg = XElement.Parse(rss).<story>.<description>; returndigg; } Click

  30. [2/12] Invoke some functions; get back “downTask” from the API UIthread IOCP thread async voidbutton1_Click() {vardiggTask= GetDiggAsync(); vardigg= awaitdiggTask; textBox1.Text = digg; } async Task<string> GetDiggAsync() {varweb = newWebClient(); vardownTask = web.DownTaskAsync("http://digg.com"); varrss= awaitdownTask; vardigg = XElement.Parse(rss).<story>.<description>; returndigg; } Click downTask

  31. [3/12] “await downTask” assigns a continuation and returns diggTask UIthread IOCP thread async voidbutton1_Click() {vardiggTask= GetDiggAsync(); vardigg= awaitdiggTask; textBox1.Text = digg; } async Task<string> GetDiggAsync() {varweb = newWebClient(); vardownTask = web.DownTaskAsync("http://digg.com"); varrss= awaitdownTask; vardigg = XElement.Parse(rss).<story>.<description>; returndigg; } Click diggTask downTask downTask»ui.Post{Κ1} Κ1:

  32. [4/12] “await diggTask” assigns a continuation and returns UIthread IOCP thread async voidbutton1_Click() {vardiggTask= GetDiggAsync(); vardigg= awaitdiggTask; textBox1.Text = digg; } async Task<string> GetDiggAsync() {varweb = newWebClient(); vardownTask = web.DownTaskAsync("http://digg.com"); varrss= awaitdownTask; vardigg = XElement.Parse(rss).<story>.<description>; returndigg; } Click diggTask»ui.Post{Κ2} diggTask downTask»ui.Post{Κ1} Κ1: Κ2:

  33. [5/12] Network packet arrives with data UIthread IOCP thread async voidbutton1_Click() {vardiggTask= GetDiggAsync(); vardigg= awaitdiggTask; textBox1.Text = digg; } async Task<string> GetDiggAsync() {varweb = newWebClient(); vardownTask = web.DownTaskAsync("http://digg.com"); varrss= awaitdownTask; vardigg = XElement.Parse(rss).<story>.<description>; returndigg; } Click diggTask»ui.Post{Κ2} downTask»ui.Post{Κ1} rss Κ1: Κ2:

  34. [6/12] Invoke downTask’s continuation with that data UIthread IOCP thread async voidbutton1_Click() {vardiggTask= GetDiggAsync(); vardigg= awaitdiggTask; textBox1.Text = digg; } async Task<string> GetDiggAsync() {varweb = newWebClient(); vardownTask = web.DownTaskAsync("http://digg.com"); varrss= awaitdownTask; vardigg = XElement.Parse(rss).<story>.<description>; returndigg; } Click diggTask»ui.Post{Κ2} downTask»ui.Post{Κ1} rss ui.Post{Κ1(rss)} Κ1: Κ2:

  35. [7/12] Continuation is a “Post”, i.e. addition to the UI queue UIthread IOCP thread async voidbutton1_Click() {vardiggTask= GetDiggAsync(); vardigg= awaitdiggTask; textBox1.Text = digg; } async Task<string> GetDiggAsync() {varweb = newWebClient(); vardownTask = web.DownTaskAsync("http://digg.com"); varrss= awaitdownTask; vardigg = XElement.Parse(rss).<story>.<description>; returndigg; } Click diggTask»ui.Post{Κ2} rss ui.Post{Κ1(rss)} Κ1: K1(rss) Κ2:

  36. [8/12] UI thread executes K1, giving a result to the “await” UIthread IOCP thread async voidbutton1_Click() {vardiggTask= GetDiggAsync(); vardigg= awaitdiggTask; textBox1.Text = digg; } async Task<string> GetDiggAsync() {varweb = newWebClient(); vardownTask = web.DownTaskAsync("http://digg.com"); varrss= awaitdownTask; vardigg = XElement.Parse(rss).<story>.<description>; returndigg; } Click diggTask»ui.Post{Κ2} rss ui.Post{Κ1(rss)} Κ1: K1(rss) Κ2:

  37. [9/12] “Return story” will signal completion of task UIthread IOCP thread async voidbutton1_Click() {vardiggTask= GetDiggAsync(); vardigg= awaitdiggTask; textBox1.Text = digg; } async Task<string> GetDiggAsync() {varweb = newWebClient(); vardownTask = web.DownTaskAsync("http://digg.com"); varrss= awaitdownTask; vardigg = XElement.Parse(rss).<story>.<description>; returndigg; } Click diggTask»ui.Post{Κ2} rss ui.Post{Κ1(rss)} Κ1: K1(rss) Κ2:

  38. [10/12] Invoke diggTask’s continuation with data (by posting to UI queue) UIthread IOCP thread async voidbutton1_Click() {vardiggTask= GetDiggAsync(); vardigg= awaitdiggTask; textBox1.Text = digg; } async Task<string> GetDiggAsync() {varweb = newWebClient(); vardownTask = web.DownTaskAsync("http://digg.com"); varrss= awaitdownTask; vardigg = XElement.Parse(rss).<story>.<description>; returndigg; } Click diggTask»ui.Post{Κ2} rss ui.Post{Κ1(rss)} Κ1: K1(rss) ui.Post(Κ2(story)) Κ2: K2(story)

  39. [11/12] Return from handling the K1 continuation UIthread IOCP thread async voidbutton1_Click() {vardiggTask= GetDiggAsync(); vardigg= awaitdiggTask; textBox1.Text = digg; } async Task<string> GetDiggAsync() {varweb = newWebClient(); vardownTask = web.DownTaskAsync("http://digg.com"); varrss= awaitdownTask; vardigg = XElement.Parse(rss).<story>.<description>; returndigg; } Click rss ui.Post{Κ1(rss)} Κ1: K1(rss) ui.Post(Κ2(story)) Κ2: K2(story)

  40. [12/12] UI thread executes K2, giving a result to the “await” UIthread IOCP thread async voidbutton1_Click() {vardiggTask= GetDiggAsync(); vardigg= awaitdiggTask; textBox1.Text = digg; } async Task<string> GetDiggAsync() {varweb = newWebClient(); vardownTask = web.DownTaskAsync("http://digg.com"); varrss= awaitdownTask; vardigg = XElement.Parse(rss).<story>.<description>; returndigg; } Click rss ui.Post{Κ1(rss)} Κ1: K1(rss) ui.Post(Κ2(story)) Κ2: K2(story)

  41. SINGLE-THREADED ASYNCHRONY AND CONCURRENCY is when we run asynchronous and concurrent tasks with NO additional threads (beyond those that the operating system already provides). No worries about mutexes &c. If you want extra threads, create them explicitly through Task.Run.

  42. “a language+framework push for compositional asynchrony” language 1. Demo/th 2. Language 3. Framework 4. Design 5. Theory

  43. 2. Language feature, explained as a syntactic rewrite async Task<string> GetDiggAsync(intp) { varx = await t; return x; } Over the following slideswe’ll see how the compiler rewritesthis async method…

  44. 2. Language [1/4] async Task<string> GetDiggAsync(intp) { varx = await t; return x; } TaskAwaiter<string> _temp; _temp = t.GetAwaiter(); _temp.BeginAwait(K1);return; K1: varx = _temp.EndAwait(); The type of _temp is whatever t.GetAwaiter() returns. This is a syntactic expansion: it binds using normal language rules (overload resolution, extension methods, …). TaskAwaiter’s implementation resumes back on the same SynchronizationContext.

  45. 2. Language [1/4] async Task<string> GetDiggAsync(intp) { varx = await t; return x; } TaskAwaiter<string> _temp; _temp = t.GetAwaiter(); if (_temp.BeginAwait(K1))return; K1: varx = _temp.EndAwait(); Actually we use an “if” statement to allow a fast-path: if “e” had already finished, it can decide to skip all the continuation machinery.

  46. 2. Language [1/4] async Task<string> GetDiggAsync(intp) { TaskAwaiter<string> _temp; _temp = t.GetAwaiter(); if (_temp.BeginAwait(K1)) return; K1: var x = _temp.EndAwait(); return x; }

  47. 2. Language [2/4] async Task<string> GetDiggAsync(intp) { TaskAwaiter<string> _temp; _temp = t.GetAwaiter(); if (_temp.BeginAwait(K1)) return; K1: var x = _temp.EndAwait(); return x; } var _builder =AsyncMethodBuilder<string>.Create(); int_state = 0; Action_moveNext = delegate { ... System.Runtime.CompilerServices.AsyncMethodBuilder<T> ...} _moveNext(); return_builder.Task;

  48. 2. Language [2/4] async Task<string> GetDiggAsync(intp) { var_builder = AsyncMethodBuilder<string>.Create(); TaskAwaiter<string> _temp; int_state = 0; Action _moveNext= delegate { _temp = t.GetAwaiter(); if (_temp.BeginAwait(K1)) return; K1: var x = _temp.EndAwait(); return x; } _moveNext(); return _builder.Task; }

  49. 2. Language [3/4] async Task<string> GetDiggAsync(int p) { var _builder = AsyncMethodBuilder<string>.Create(); TaskAwaiter<string> _temp; int _state = 0; Action _moveNext = delegate { _temp = t.GetAwaiter(); if (_temp.BeginAwait(K1)) return; K1: var x = _temp.EndAwait(); return x; } _moveNext(); return _builder.Task; } try { //... jump table based on _state _state = 1; _moveNext _state = 0; _builder.SetResult(r); return; catch (Exception ex) { _builder.SetException(ex);}

  50. 2. Language [3/4] async Task<string> GetDiggAsync(intp) { var _builder = AsyncMethodBuilder<string>.Create(); TaskAwaiter<string> _temp; int _state = 0; Action _moveNext = delegate{ try { //... jump table based on _state _temp = t.GetAwaiter(); _state = 1; if(_temp.BeginAwait(_moveNext)) return; K1: _state = 0; var x = _temp.EndAwait(); _builder.SetResult(x); return; } catch (Exception ex) { _builder.SetException(ex); } } _moveNext(); return _builder.Task; }

More Related