the evolution of async-programming on .net platform (tup, full)

79
The Evolution of Async Programming on .NET Platform ZhaoJie @ SNDA Nov, 2010

Upload: jeffz

Post on 10-May-2015

3.776 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: The Evolution of Async-Programming on .NET Platform (TUP, Full)

The Evolution of Async Programming on .NET Platform

ZhaoJie @ SNDANov, 2010

Page 2: The Evolution of Async-Programming on .NET Platform (TUP, Full)

About Me

• 赵劼 / 老赵 / Jeffrey Zhao / 赵姐夫

• 日写代码三百行,不辞长做程序员• Blog: http://blog.zhaojie.me/

• Twitter: @jeffz_cn

• F#, Scala, JavaScript, Python, .NET, mono...

• Java (as the language) hater

Page 3: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Agenda

• Why & How

• .NET 1.0

• .NET 2.0 / C# 2.0

• .NET 3.0 / F#

• .NET 4.0 / Reactive Framework

• Future / C# vNext

Page 4: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Why?

Because the essence ofCloud, Web, Mobile

is asynchronous computations

Page 5: The Evolution of Async-Programming on .NET Platform (TUP, Full)

How?

By providing powerful language features / programming model /

libraries

Page 6: The Evolution of Async-Programming on .NET Platform (TUP, Full)

.NET 1.0

Page 7: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Two Raw Async Models

• Begin/End

• Event-based

• Both are callback-based• Which is just “asynchronous” means

Page 8: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Begin/End Async Modeldelegate AsyncCallback(IAsyncResult);

interface IAsyncResult { object AsyncState { get; } WaitHandle AsyncWaitHandle { get; } bool CompletedSynchronously { get; } bool IsCompleted { get; }}

void BeginXxx(arg1, arg2, ..., AsyncCallback, state);

TResult EndXxx(IAsyncResult);

Page 9: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Let’s write a “Transfer” method in 4 different

ways

Page 10: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Syncpublic static void Transfer(string url, Stream streamOut) { var request = WebRequest.Create(url); using (var response = request.GetResponse()) { var streamIn = response.GetResponseStream();

var size = 1024; var buffer = new byte[size]; while (true) { var lengthRead = streamIn.Read(buffer, 0, size); if (lengthRead <= 0) break; streamOut.Write(buffer, 0, lengthRead); } }}

Page 11: The Evolution of Async-Programming on .NET Platform (TUP, Full)

AsyncIAsyncResult BeginTransfer(url, streamOut, ..., callback) { // keep context and BeginGetResponse}

void EndGetResponse(...) { // get streamIn and BeginRead}

void EndRead(...) { // data read, completed or BeginWrite}

void EndWrite(...) { // data wrote, BeginRead}

Page 12: The Evolution of Async-Programming on .NET Platform (TUP, Full)

AsyncIAsyncResult BeginTransfer(url, streamOut, ..., callback) { // keep context and BeginGetResponse}

void EndGetResponse(...) { // get streamIn and BeginRead}

void EndRead(...) { // data read, completed or BeginWrite}

void EndWrite(...) { // data wrote, BeginRead}

1

Page 13: The Evolution of Async-Programming on .NET Platform (TUP, Full)

AsyncIAsyncResult BeginTransfer(url, streamOut, ..., callback) { // keep context and BeginGetResponse}

void EndGetResponse(...) { // get streamIn and BeginRead}

void EndRead(...) { // data read, completed or BeginWrite}

void EndWrite(...) { // data wrote, BeginRead}

1

2

Page 14: The Evolution of Async-Programming on .NET Platform (TUP, Full)

AsyncIAsyncResult BeginTransfer(url, streamOut, ..., callback) { // keep context and BeginGetResponse}

void EndGetResponse(...) { // get streamIn and BeginRead}

void EndRead(...) { // data read, completed or BeginWrite}

void EndWrite(...) { // data wrote, BeginRead}

1

2

3

Page 15: The Evolution of Async-Programming on .NET Platform (TUP, Full)

AsyncIAsyncResult BeginTransfer(url, streamOut, ..., callback) { // keep context and BeginGetResponse}

void EndGetResponse(...) { // get streamIn and BeginRead}

void EndRead(...) { // data read, completed or BeginWrite}

void EndWrite(...) { // data wrote, BeginRead}

1

2

4

3

Page 16: The Evolution of Async-Programming on .NET Platform (TUP, Full)

AsyncIAsyncResult BeginTransfer(url, streamOut, ..., callback) { // keep context and BeginGetResponse}

void EndGetResponse(...) { // get streamIn and BeginRead}

void EndRead(...) { // data read, completed or BeginWrite}

void EndWrite(...) { // data wrote, BeginRead}

1

2

4

3

5

Page 17: The Evolution of Async-Programming on .NET Platform (TUP, Full)

AsyncIAsyncResult BeginTransfer(url, streamOut, ..., callback) { // keep context and BeginGetResponse}

void EndGetResponse(...) { // get streamIn and BeginRead}

void EndRead(...) { // data read, completed or BeginWrite}

void EndWrite(...) { // data wrote, BeginRead}

1

2

4

3

5

6

Page 18: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Robust & Syncpublic void Transfer(string url, Stream streamOut) { try { var request = WebRequest.Create(url); using (var response = request.GetResponse()) { var streamIn = response.GetResponseStream();

var size = 1024; var buffer = new byte[size]; while (true) { var lengthRead = streamIn.Read(buffer, 0, size); if (lengthRead <= 0) break; streamIn.Write(buffer, 0, lengthRead); } } } catch { // ... }}

Page 19: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Robust & AsyncIAsyncResult BeginTransfer(url, streamOut, ..., callback) { try { ... } catch { ... }}

void EndGetResponse(...) { try { ... } catch { ... }}

void EndRead(...) { try { ... } catch { ... }}

void EndWrite(...) { try { ... } catch { ... }}

Page 20: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Event-based Async Model

class XxxCompletedEventArgs : EventArgs { Exception Error { get; } TResult Result { get; }}

class Worker { event EventHandler<XxxCompletedArgs> XxxCompleted; void XxxAsync(arg1, arg2, ...);}

Page 21: The Evolution of Async-Programming on .NET Platform (TUP, Full)
Page 22: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Code Locality is Broken

• Used to expressing algorithms linearly

• Async requires logical division of algorithms• No if / using / while / for ...

• Very difficult to• Combine multiple asynchronous operations

• Deal with exceptions and cancellation

Page 23: The Evolution of Async-Programming on .NET Platform (TUP, Full)

.NET 2.0 / C# 2.0

Page 24: The Evolution of Async-Programming on .NET Platform (TUP, Full)

“yield” for Iterators

IEnumerable<int> Numbers() { yield return 0; yield return 1; yield return 2;

}

Page 25: The Evolution of Async-Programming on .NET Platform (TUP, Full)

“yield” for Iterators

IEnumerable<int> Numbers() { yield return 0; yield return 1; yield return 2;

}

MoveNext()

Page 26: The Evolution of Async-Programming on .NET Platform (TUP, Full)

“yield” for Iterators

IEnumerable<int> Numbers() { yield return 0; yield return 1; yield return 2;

}

MoveNext()

MoveNext()

Page 27: The Evolution of Async-Programming on .NET Platform (TUP, Full)

“yield” for Iterators

IEnumerable<int> Numbers() { yield return 0; yield return 1; yield return 2;

}

MoveNext()

MoveNext()

MoveNext()

Page 28: The Evolution of Async-Programming on .NET Platform (TUP, Full)

“yield” for Iterators

IEnumerable<int> Numbers() { yield return 0; yield return 1; yield return 2;

}

MoveNext()

MoveNext()

MoveNext()

MoveNext()

Page 29: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Async with “yield”IEnumerator<int> Transfer(AsyncEnumerator ae, string url, Stream streamOut) { var request = WebRequest.Create(url); request.BeginGetResponse(ae.End(), null); yield return 1;

using (var response = request.EndGetResponse(ae.DequeueAsyncResult())) { var streamIn = response.GetResponseStream(); byte[] buffer = new byte[1024]; while (true) { streamIn.BeginRead(buffer, 0, buffer.Length, ae.End(), null); yield return 1;

int lengthRead = streamIn.EndRead(ae.DequeueAsyncResult()); if (lengthRead <= 0) break; streamOut.BeginWrite(buffer, 0, lengthRead, ae.End(), null); yield return 1;

streamOut.EndWrite(ae.DequeueAsyncResult()); } }}

Page 30: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Async with “yield”IEnumerator<int> Transfer(AsyncEnumerator ae, string url, Stream streamOut) { var request = WebRequest.Create(url); request.BeginGetResponse(ae.End(), null); yield return 1;

using (var response = request.EndGetResponse(ae.DequeueAsyncResult())) { var streamIn = response.GetResponseStream(); byte[] buffer = new byte[1024]; while (true) { streamIn.BeginRead(buffer, 0, buffer.Length, ae.End(), null); yield return 1;

int lengthRead = streamIn.EndRead(ae.DequeueAsyncResult()); if (lengthRead <= 0) break; streamOut.BeginWrite(buffer, 0, lengthRead, ae.End(), null); yield return 1;

streamOut.EndWrite(ae.DequeueAsyncResult()); } }}

“yield” after firing async operations

Page 31: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Async with “yield”IEnumerator<int> Transfer(AsyncEnumerator ae, string url, Stream streamOut) { var request = WebRequest.Create(url); request.BeginGetResponse(ae.End(), null); yield return 1;

using (var response = request.EndGetResponse(ae.DequeueAsyncResult())) { var streamIn = response.GetResponseStream(); byte[] buffer = new byte[1024]; while (true) { streamIn.BeginRead(buffer, 0, buffer.Length, ae.End(), null); yield return 1;

int lengthRead = streamIn.EndRead(ae.DequeueAsyncResult()); if (lengthRead <= 0) break; streamOut.BeginWrite(buffer, 0, lengthRead, ae.End(), null); yield return 1;

streamOut.EndWrite(ae.DequeueAsyncResult()); } }}

“yield” after firing async operations

continue when async operations

completed

Page 32: The Evolution of Async-Programming on .NET Platform (TUP, Full)

“yield return” for Async

• Coming with new programming patterns

• Keep code locality• Good parts: support if / using / while / for ...

• But not perfect: cannot use try...catch

• The primitives for Fibers - lightweight computation units

Page 33: The Evolution of Async-Programming on .NET Platform (TUP, Full)

.NET 3.0 / F#

Page 34: The Evolution of Async-Programming on .NET Platform (TUP, Full)

F#

• Language by Don Syme, MS Research

• Strongly statically typed language

• Functional language with OO ability

• For industry and education• Open source (Apache 2.0)

• Cross-platform supported by Microsoft

Page 35: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Concurrency Challenges

• Shared State - Immutability

• Code Locality - async { ... }

• I/O Parallelism - async { ... }

• Scaling to Multi-Machine - Agents with async { ... }

Page 36: The Evolution of Async-Programming on .NET Platform (TUP, Full)

What’s async { ... }

... the principle we go by is, don't expect to see a particular concurrency model put into C# because there're many different concurrency model ... it's more about finding things are common to to all kinds of concurrency ...

- Anders Hejlsberg

Page 37: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Async Workflow

async {   let! res = <async work> ...}

Page 38: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Async Workflow

async {   let! res = <async work> ...}

React!

Page 39: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Async Workflow

async {   let! res = <async work> ...}

React!

an HTTP Responsean UI Event

a Timer Callbacka Query Response

a Web Servcie Responsea Disk I/O Completion

an Agent Message

Page 40: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Async in F#let transferAsync (url: string) (streamOut: Stream) = async {

let request = WebRequest.Create(url) use! response = request.AsyncGetResponse() let streamIn = response.GetResponseStream() let rec transferDataAsync (buffer: byte[]) = async { let! lengthRead = streamIn.AsyncRead(buffer, 0, buffer.Length) if lengthRead > 0 then do! streamOut.AsyncWrite(buffer, 0, lengthRead) do! transferDataAsync buffer } do! transferDataAsync (Array.zeroCreate 1024)}

Page 41: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Async in F#let transferAsync (url: string) (streamOut: Stream) = async {

let request = WebRequest.Create(url) use! response = request.AsyncGetResponse() let streamIn = response.GetResponseStream() let rec transferDataAsync (buffer: byte[]) = async { let! lengthRead = streamIn.AsyncRead(buffer, 0, buffer.Length) if lengthRead > 0 then do! streamOut.AsyncWrite(buffer, 0, lengthRead) do! transferDataAsync buffer } do! transferDataAsync (Array.zeroCreate 1024)}

simply generate from Begin/End methods

AsyncGetResponse

AsyncRead

AsyncWrite

Page 42: The Evolution of Async-Programming on .NET Platform (TUP, Full)

How async { ... } Worksasync { let! img = AsyncRead "http://..." printfn "loaded!" do! AsyncWrite img @"c:\..." printfn "saved!" }

Page 43: The Evolution of Async-Programming on .NET Platform (TUP, Full)

How async { ... } Worksasync { let! img = AsyncRead "http://..." printfn "loaded!" do! AsyncWrite img @"c:\..." printfn "saved!" }

async.Delay(fun -> async.Bind(AsyncRead "http://...", (fun img -> printfn "loaded!" async.Bind(AsyncWrite img @"c:\...", (fun () -> printfn "saved!" async.Return())))))

=

Page 44: The Evolution of Async-Programming on .NET Platform (TUP, Full)

F# Async Workflow• Library, not a language feature• Based on Computation Expressions in F#

• Support all kinds of language constructions• Error handling: try...catch

• Loop: while / for (like “foreach” in C#)

• Others: if / use (like “using” in C#), etc.

• Easy to• Combine multiple asynchronous operations

• Deal with exceptions and cancellation

Page 45: The Evolution of Async-Programming on .NET Platform (TUP, Full)

F# Resourceshttp://fsharp.net

Programming F# Expert F# 2.0 Real World FP

Page 46: The Evolution of Async-Programming on .NET Platform (TUP, Full)

.NET 4.0 / Reactive Framework

Page 47: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Reactive Framework

Fundamentally change the way you think about coordinating and

orchestrating asynchronous and event-based programming

Page 48: The Evolution of Async-Programming on .NET Platform (TUP, Full)

How

By showing that asynchronous and event-base computations are just

push-based collections

Page 49: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Environment

Program

Interactive Reactive

Page 50: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Enumerable Collections

interface IEnumerable<out T> { IEnumerator<T> GetEnumerator();}

interface IEnumerator<out T> { bool MoveNext(); T Current { get; }}

Page 51: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Dualize

Page 52: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Observable Collections

interface IObservable<out T> { IDisposable Subscribe(IObserver<T> o)}

interface IObserver<in T> { void OnCompleted(); void OnNext(T item); void OnError(Exception ex);}

Page 53: The Evolution of Async-Programming on .NET Platform (TUP, Full)

IEnumerable & IEnumerator are prototypical interfaces for interactive collections and interactive programs.

IObservable & IObserver are prototypical interfaces for observable collections and reactive, asynchronous & event-based programs.

Page 54: The Evolution of Async-Programming on .NET Platform (TUP, Full)

LINQ to Observable

If you are writingLINQ or declarative codein an interactive program...

Page 55: The Evolution of Async-Programming on .NET Platform (TUP, Full)

LINQ to Observable

If you are writingLINQ or declarative codein an interactive program...

You already know how to use it!

Page 56: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Again

... the principle we go by is, don't expect to see a particular concurrency model put into C# because there're many different concurrency model ... it's more about finding things are common to to all kinds of concurrency ...

- Anders Hejlsberg

Page 57: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Again

... the principle we go by is, don't expect to see a particular concurrency model put into C# because there're many different concurrency model ... it's more about finding things are common to to all kinds of concurrency ...

- Anders Hejlsberg

Page 58: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Move by WASD// filter the KeyPress events when playingvar keyPress = GetKeyPress().Where(_ => isPlaying);

// filter the events to move leftvar moveLeft = from ev in keyPress where ev.EventArgs.KeyChar == 'a' where ball.Left > 0 select ev;moveLeft.Subscribe(_ => ball.Left -= 5);

// filter the events to move topvar moveTop = from ev in keyPress where ev.EventArgs.KeyChar == 'w' where ball.Top > 0 select ev;moveTop.Subscribe(_ => ball.Top -= 5);

Page 59: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Mouse Drag and Drawvar mouseMove = GetMouseMove();var mouseDiff = mouseMove.Zip(mouseMove.Skip(1), (prev, curr) => new { PrevPos = new Point( prev.EventArgs.X, prev.EventArgs.Y), CurrPos = new Point( curr.EventArgs.X, curr.EventArgs.Y) });

var mouseDrag = from _ in GetMouseDown() from diff in mouseDiff.TakeUntil(GetMouseUp()) select diff;

mouseDrag.Subscribe(d => DrawLine(d.PrevPos, d.CurrPos));

Page 60: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Everything in Web is Asynchronous

• User actions

• AJAX requests

• Animations

• ...

Page 61: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Rx in JavaScript

• A full featured port for JavaScript• Easy-to-use conversions from existing DOM,

XmlHttpRequest, etc

• In a download size of less than 7kb (gzipped)

• Bindings for various libraries / frameworks• jQuery

• MooTools

• Dojo

• ...

Page 62: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Drag and Draw in JSvar target = $("#paintPad");var mouseMove = target.toObservable("mousemove");var mouseDiff = mouseMove.Zip(mouseMove.Skip(1), function(prev, curr) { return { prevPos: { x: prev.clientX, y: prev.clientY }, currPos: { x: curr.clientX, y: curr.clientY } }; });

var mouseDown = target.toObservable("mousedown");var mouseUp = target.toObservable("mouseup");var mouseDrag = mouseDown.SelectMany(function() { mouseDiff.TakeUntil(mouseUp);});

mouseDrag.Subscribe( function(d) { drawLine(d.prevPos, d.currPos); });

Page 63: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Wikipedia Lookupvar textBox = $("#searchInput");var searcher = textBox .toObservable("keyup") .Throttle(500) .Select(function(_) { return textBox.val(); }) .Select(function(term) { return queryWikipedia(term); }) .Switch();

searcher.Subscribe( function(data) { var results = $("#results"); results.empty(); $.each(data, function(_, value) { results.append($("<li/>").text(value)); }); }, function(error) { $("#error").html(error); });

Page 64: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Time Flies like an Arrowvar container = $("#container");var mouseMove = container.toObservable("mousemove");

for (var i = 0; i < text.length; i++) { (function(i) { var ele = $("<span/>").text(text.charAt(i)); ele.css({position: "absolute"}).appendTo(container);

mouseMove.Delay(i * 100).Subscribe(function (ev) { ele.css({ left: ev.clientX + i * 20 + 15 + "px", top: ev.clientY + "px" }); });

})(i);

Page 65: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Benefits of Rx

• Easy to composite and coordinate async operations

• Express the algorithm in functional ways• Helper method: For / While / If / Try / Switch...

• Easy to be unit tested

• ...

Page 66: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Rx & Language Features

• Features in C# that Rx uses• Extension method

• Lambda expression & closure

• Type inference

• LINQ query expression

• Rx has been implemented in ...• C# & VB

• JavaScript

• F#

Page 67: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Portability

• Rx can be easily ported to various languages• Scala

• Ruby

• Python

• modern languages with basic functional features

• Almost impossible to implement Rx in Java• Cannot extend a type without breaking code

• Missing enough functional features

Page 68: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Rx Resources

• Matthew Podwysocki• http://codebetter.com/blogs/matthew.podwysocki/

• Reactive Framework on MSDN DevLabs• http://msdn.microsoft.com/en-us/devlabs/

ee794896.aspx

• Tomáš Petříček• http://tomasp.net/

Page 69: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Comparison

• F# Async Workflow• Elegant, simple, easy to use

• Can only be used at server-side (WebSharper come to rescure?)

• Reactive Framework• Can be used at both server-side and client-side.

• New async model brings learning cost.

Page 70: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Out of Topic

Can we programming like F# in JavaScript?

Page 71: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Jscex & Jscex.Async

• Computation Expressions and Async Workflow implemented in JavaScript

• http://github.com/jeffreyzhao/jscex

Page 72: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Clock

var drawClockAsync = eval(Jscex.compile("$async", function(interval) { while (true) { drawClock(new Date()); $await(Jscex.Async.sleep(interval)); } }));

Jscex.Async.start(drawClockAsync(1000));

Page 73: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Animationvar moveAsync = eval(Jscex.compile("$async", function(e, start, end, duration) { for (var t = 0; t < duration; t += 50) { e.style.left = start.x + (end.x - start.x) * t / duration; e.style.top = start.y + (end.y - start.y) * t / duration; $await(Jscex.Async.sleep(50)); }

e.style.left = end.x; e.style.top = end.y; }));

var moveSquareAsync = eval(Jscex.compile("$async", function(e) { $await(moveAsync(e, {x:100, y:100}, {x:400, y:100}, 1000)); $await(moveAsync(e, {x:400, y:100}, {x:400, y:400}, 1000)); $await(moveAsync(e, {x:400, y:400}, {x:100, y:400}, 1000)); $await(moveAsync(e, {x:100, y:400}, {x:100, y:100}, 1000));}));

Page 74: The Evolution of Async-Programming on .NET Platform (TUP, Full)

C# vNext

Page 75: The Evolution of Async-Programming on .NET Platform (TUP, Full)

async Task<XElement> GetRssAsync(string url) { var client = new WebClient(); var task = client.DownloadStringTaskAsync(url); var text = await task; var xml = XElement.Parse(text); return xml;}

Source

Page 76: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Task<XElement> GetRssAsync(string url) { var $builder = AsyncMethodBuilder<XElement>.Create(); var $state = 0; TaskAwaiter<string> $a1; Action $resume = delegate { try { if ($state == 1) goto L1; var client = new WebClient(); var task = client.DownloadStringTaskAsync(url); $state = 1; $a1 = task.GetAwaiter(); if ($a1.BeginAwait($resume)) return; L1: var text = $a1.EndAwait(); var xml = XElement.Parse(text); $builder.SetResult(xml); } catch (Exception $ex) { $builder.SetException($ex); } }; $resume(); return $builder.Task;}

Compiled

Page 77: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Conclusion

• Async Programming is difficult

• New programming language / feature / library / model can help

Page 78: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Q & A

Page 79: The Evolution of Async-Programming on .NET Platform (TUP, Full)

Thanks