SlideShare a Scribd company logo
The Evolution of Async
Programming on .NET Platform
          ZhaoJie @ SNDA
             Nov, 2010
About Me
•       /        / Jeffrey Zhao /

•
• Blog: http://blog.zhaojie.me/
• Twitter: @jeffz_cn
• F#, Scala, JavaScript, Python, .NET, mono...
• Java (as the language) hater
Agenda
• Why & How
• .NET 1.0
• .NET 2.0 / C# 2.0
• .NET 3.0 / F#
• .NET 4.0 / Reactive Framework
• Future / C# vNext
Why?


   Because the essence of
      Cloud, Web, Mobile
is asynchronous computations
How?


 By providing powerful language
features / programming model /
             libraries
.NET 1.0
Two Raw Async Models

• Begin/End
• Event-based
• Both are callback-based
 •   Which is just “asynchronous” means
Begin/End Async Model
delegate 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);
Let’s write a “Transfer”
 method in 4 different
          ways
Sync
public 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);
        }
    }
}
Async
IAsyncResult 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
}
Async
1   IAsyncResult 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
    }
Async
1   IAsyncResult BeginTransfer(url, streamOut, ..., callback) {
        // keep context and BeginGetResponse
    }
                   2
    void EndGetResponse(...) {
        // get streamIn and BeginRead
    }

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

    void EndWrite(...) {
        // data wrote, BeginRead
    }
Async
1   IAsyncResult BeginTransfer(url, streamOut, ..., callback) {
        // keep context and BeginGetResponse
    }
                   2
    void EndGetResponse(...) {
        // get streamIn and BeginRead
    }
                   3
    void EndRead(...) {
        // data read, completed or BeginWrite
    }

    void EndWrite(...) {
        // data wrote, BeginRead
    }
Async
1   IAsyncResult BeginTransfer(url, streamOut, ..., callback) {
        // keep context and BeginGetResponse
    }
                   2
    void EndGetResponse(...) {
        // get streamIn and BeginRead
    }
                   3
    void EndRead(...) {
        // data read, completed or BeginWrite
    }
                   4

    void EndWrite(...) {
        // data wrote, BeginRead
    }
Async
1   IAsyncResult BeginTransfer(url, streamOut, ..., callback) {
        // keep context and BeginGetResponse
    }
                   2
    void EndGetResponse(...) {
        // get streamIn and BeginRead
    }
                   3
    void EndRead(...) {
        // data read, completed or BeginWrite
    }
5                  4

    void EndWrite(...) {
        // data wrote, BeginRead
    }
Async
1   IAsyncResult BeginTransfer(url, streamOut, ..., callback) {
        // keep context and BeginGetResponse
    }
                   2
    void EndGetResponse(...) {
        // get streamIn and BeginRead
    }
                   3
    void EndRead(...) {
        // data read, completed or BeginWrite      6
    }
5                  4

    void EndWrite(...) {
        // data wrote, BeginRead
    }
Robust & Sync
public 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 {
        // ...
    }
}
Robust & Async
IAsyncResult BeginTransfer(url, streamOut, ..., callback) {
    try { ... } catch { ... }
}

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

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

void EndWrite(...) {
    try { ... } catch { ... }
}
Event-based Async Model
class XxxCompletedEventArgs : EventArgs {
    Exception Error { get; }
    TResult Result { get; }
}

class Worker {
    event EventHandler<XxxCompletedArgs> XxxCompleted;
    void XxxAsync(arg1, arg2, ...);
}
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
.NET 2.0 / C# 2.0
“yield” for Iterators
  IEnumerable<int> Numbers() {

      yield return 0;
  	
      yield return 1;
  	
      yield return 2;

  }
“yield” for Iterators
             IEnumerable<int> Numbers() {
MoveNext()
                 yield return 0;
             	
                 yield return 1;
             	
                 yield return 2;

             }
“yield” for Iterators
             IEnumerable<int> Numbers() {
MoveNext()
                 yield return 0;
             	
MoveNext()
                 yield return 1;
             	
                 yield return 2;

             }
“yield” for Iterators
             IEnumerable<int> Numbers() {
MoveNext()
                 yield return 0;
             	
MoveNext()
                 yield return 1;
             	
MoveNext()
                 yield return 2;

             }
“yield” for Iterators
             IEnumerable<int> Numbers() {
MoveNext()
                 yield return 0;
             	
MoveNext()
                 yield return 1;
             	
MoveNext()
                 yield return 2;
MoveNext()
             }
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());
        }
    }
}
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” after       yield return 1;
firing async
operations
                  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());
              }
         }
    }
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” after       yield return 1;
firing async
operations
                  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());           continue when
              }                                                         async operations
         }                                                                 completed
    }
“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
.NET 3.0 / F#
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
Concurrency Challenges

• Shared State - Immutability
• Code Locality - async { ... }
• I/O Parallelism - async { ... }
• Scaling to Multi-Machine - Agents with
  async { ... }
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
Async Workflow
async { 	
    let! res = <async work>
    ...	
}
Async Workflow
            React!
async { 	
    let! res = <async work>
    ...	
}
Async Workflow
              React!
async { 	
    let! res = <async work>
    ...	
}
        an HTTP Response
            an UI Event
         a Timer Callback
        a Query Response
     a Web Servcie Response
      a Disk I/O Completion
         an Agent Message
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)
}
Async in F#
let transferAsync (url: string) (streamOut: Stream) = async {

    let request = WebRequest.Create(url)
    use! response = request.AsyncGetResponse()
                            AsyncGetResponse
    let streamIn = response.GetResponseStream()

    let rec transferDataAsync (buffer: byte[]) = async {
        let! lengthRead = streamIn.AsyncRead(buffer, 0, buffer.Length)
                                   AsyncRead
        if lengthRead > 0 then
            do! streamOut.AsyncWrite(buffer, 0, lengthRead)
                          AsyncWrite
            do! transferDataAsync buffer
    }
                                                      simply generate from
    do! transferDataAsync (Array.zeroCreate 1024)      Begin/End methods
}
How async { ... } Works
   async {
       let! img = AsyncRead "http://..."
       printfn "loaded!"
       do! AsyncWrite img @"c:..."
       printfn "saved!" }
How async { ... } Works
       async {
           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())))))
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
F# Resources
                 http://fsharp.net




Programming F#     Expert F# 2.0     Real World FP
.NET 4.0 / Reactive
   Framework
Reactive Framework

 Fundamentally change the way you
   think about coordinating and
  orchestrating asynchronous and
     event-based programming
How


By showing that asynchronous and
 event-base computations are just
      push-based collections
Interactive                 Reactive
              Environment



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

 interface IEnumerator<out T> {
     bool MoveNext();
     T Current { get; }
 }
Dualize
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);
}
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.
LINQ to Observable

        If you are writing
    LINQ or declarative code
   in an interactive program...
LINQ to Observable

         If you are writing
     LINQ or declarative code
    in an interactive program...


  You already know how to use it!
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
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
Move by WASD
// filter the KeyPress events when playing
var keyPress = GetKeyPress().Where(_ => isPlaying);

// filter the events to move left
var 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 top
var moveTop = from ev in keyPress
              where ev.EventArgs.KeyChar == 'w'
              where ball.Top > 0
              select ev;
moveTop.Subscribe(_ => ball.Top -= 5);
Mouse Drag and Draw
var 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));
Everything in Web is
    Asynchronous
• User actions
• AJAX requests
• Animations
• ...
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
  •   ...
Drag and Draw in JS
var 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); });
Wikipedia Lookup
var 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); });
Time Flies like an Arrow
var 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);
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
• ...
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#
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
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/
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.
Out of Topic


Can we programming like F# in JavaScript?
Jscex & Jscex.Async


• Computation Expressions and Async
  Workflow implemented in JavaScript

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

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

Jscex.Async.start(drawClockAsync(1000));
Animation
var 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));
}));
C# vNext
Source

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;
}
Compiled
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;
}
Conclusion


• Async Programming is difficult
• New programming language / feature /
  library / model can help
Q &A
Thanks

More Related Content

PDF
The Evolution of Async-Programming on .NET Platform (.Net China, C#)
PDF
Jscex: Write Sexy JavaScript
PDF
The Evolution of Async-Programming (SD 2.0, JavaScript)
PDF
Javascript Uncommon Programming
PDF
Jscex: Write Sexy JavaScript (中文)
PDF
响应式编程及框架
PDF
深入浅出Jscex
PDF
Virtual machine and javascript engine
The Evolution of Async-Programming on .NET Platform (.Net China, C#)
Jscex: Write Sexy JavaScript
The Evolution of Async-Programming (SD 2.0, JavaScript)
Javascript Uncommon Programming
Jscex: Write Sexy JavaScript (中文)
响应式编程及框架
深入浅出Jscex
Virtual machine and javascript engine

What's hot (20)

PDF
12 Monkeys Inside JS Engine
PDF
Metaprogramming and Reflection in Common Lisp
PPT
About Those Python Async Concurrent Frameworks - Fantix @ OSTC 2014
PPT
Евгений Крутько, Многопоточные вычисления, современный подход.
PDF
Javascript engine performance
PDF
A deep dive into PEP-3156 and the new asyncio module
PDF
Promise: async programming hero
PPT
PDF
asyncio internals
PDF
Apache PIG - User Defined Functions
PDF
Python Coroutines, Present and Future
ZIP
Intro to Pig UDF
PDF
Think Async: Asynchronous Patterns in NodeJS
PDF
Python meetup: coroutines, event loops, and non-blocking I/O
PDF
Python Async IO Horizon
PDF
The Ring programming language version 1.3 book - Part 84 of 88
KEY
Python Yield
PDF
[Let'Swift 2019] 실용적인 함수형 프로그래밍 워크샵
PDF
[JavaOne 2011] Models for Concurrent Programming
PDF
Easy Going Groovy 2nd season on DevLOVE
12 Monkeys Inside JS Engine
Metaprogramming and Reflection in Common Lisp
About Those Python Async Concurrent Frameworks - Fantix @ OSTC 2014
Евгений Крутько, Многопоточные вычисления, современный подход.
Javascript engine performance
A deep dive into PEP-3156 and the new asyncio module
Promise: async programming hero
asyncio internals
Apache PIG - User Defined Functions
Python Coroutines, Present and Future
Intro to Pig UDF
Think Async: Asynchronous Patterns in NodeJS
Python meetup: coroutines, event loops, and non-blocking I/O
Python Async IO Horizon
The Ring programming language version 1.3 book - Part 84 of 88
Python Yield
[Let'Swift 2019] 실용적인 함수형 프로그래밍 워크샵
[JavaOne 2011] Models for Concurrent Programming
Easy Going Groovy 2nd season on DevLOVE
Ad

Viewers also liked (7)

PPTX
Fun With Reactive Extensions
PPTX
Introduction to Reactive Extensions
PDF
Real-world applications of the Reactive Extensions
PDF
Reactive Programming in .Net - actorbased computing with Akka.Net
PDF
Why Java Sucks and C# Rocks (Final)
PDF
Intro to Reactive Programming
PDF
Reactive programming
Fun With Reactive Extensions
Introduction to Reactive Extensions
Real-world applications of the Reactive Extensions
Reactive Programming in .Net - actorbased computing with Akka.Net
Why Java Sucks and C# Rocks (Final)
Intro to Reactive Programming
Reactive programming
Ad

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

PPTX
Async Development con Visual Studio 2012
PPTX
Asynchronous Programming in ASP.NET
ODP
To Infinity & Beyond: Protocols & sequences in Node - Part 2
PDF
Reactive programming on Android
DOCX
Winform
PDF
Non Blocking I/O for Everyone with RxJava
PDF
swift-nio のアーキテクチャーと RxHttpClient
PDF
Asynchronous, Event-driven Network Application Development with Netty
PDF
Multithreading in Java
PPTX
Avoiding Callback Hell with Async.js
PPTX
Visug async
PDF
ikh331-06-distributed-programming
PDF
Server Side Swift: Vapor
PDF
Apache Beam de A à Z
PPT
JS everywhere 2011
PDF
Why async matters
PDF
服务框架: Thrift & PasteScript
PPT
Server side JavaScript: going all the way
PDF
From Node to Go
PPTX
Flink Batch Processing and Iterations
Async Development con Visual Studio 2012
Asynchronous Programming in ASP.NET
To Infinity & Beyond: Protocols & sequences in Node - Part 2
Reactive programming on Android
Winform
Non Blocking I/O for Everyone with RxJava
swift-nio のアーキテクチャーと RxHttpClient
Asynchronous, Event-driven Network Application Development with Netty
Multithreading in Java
Avoiding Callback Hell with Async.js
Visug async
ikh331-06-distributed-programming
Server Side Swift: Vapor
Apache Beam de A à Z
JS everywhere 2011
Why async matters
服务框架: Thrift & PasteScript
Server side JavaScript: going all the way
From Node to Go
Flink Batch Processing and Iterations

More from jeffz (20)

PDF
Wind.js无障碍调试与排错
PDF
JavaScript现代化排错实践
PDF
Jscex:案例、阻碍、体会、展望
PDF
Jscex:案例、经验、阻碍、展望
PDF
The Evolution of Async Programming (GZ TechParty C#)
PDF
Mono for .NET Developers
PDF
单点登录解决方案的架构与实现
PDF
Documentation Insight技术架构与开发历程
PDF
Windows Phone应用开发心得
PDF
分布式版本管理
PDF
使用.NET构建轻量级分布式框架
PDF
针对iPad平台的高性能网站架构
PDF
企业开发领域的语言特性
PDF
大话程序员可用的算法
PDF
面向对象与生活
PDF
Windows内核技术介绍
PDF
F#语言对异步程序设计的支持
PDF
大众点评网的技术变迁之路
PDF
Better Framework Better Life
PDF
如何成为一名优秀的博主
Wind.js无障碍调试与排错
JavaScript现代化排错实践
Jscex:案例、阻碍、体会、展望
Jscex:案例、经验、阻碍、展望
The Evolution of Async Programming (GZ TechParty C#)
Mono for .NET Developers
单点登录解决方案的架构与实现
Documentation Insight技术架构与开发历程
Windows Phone应用开发心得
分布式版本管理
使用.NET构建轻量级分布式框架
针对iPad平台的高性能网站架构
企业开发领域的语言特性
大话程序员可用的算法
面向对象与生活
Windows内核技术介绍
F#语言对异步程序设计的支持
大众点评网的技术变迁之路
Better Framework Better Life
如何成为一名优秀的博主

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

  • 1. The Evolution of Async Programming on .NET Platform ZhaoJie @ SNDA Nov, 2010
  • 2. About Me • / / Jeffrey Zhao / • • Blog: http://blog.zhaojie.me/ • Twitter: @jeffz_cn • F#, Scala, JavaScript, Python, .NET, mono... • Java (as the language) hater
  • 3. Agenda • Why & How • .NET 1.0 • .NET 2.0 / C# 2.0 • .NET 3.0 / F# • .NET 4.0 / Reactive Framework • Future / C# vNext
  • 4. Why? Because the essence of Cloud, Web, Mobile is asynchronous computations
  • 5. How? By providing powerful language features / programming model / libraries
  • 7. Two Raw Async Models • Begin/End • Event-based • Both are callback-based • Which is just “asynchronous” means
  • 8. Begin/End Async Model delegate 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);
  • 9. Let’s write a “Transfer” method in 4 different ways
  • 10. Sync public 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); } } }
  • 11. Async IAsyncResult 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 }
  • 12. Async 1 IAsyncResult 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 }
  • 13. Async 1 IAsyncResult BeginTransfer(url, streamOut, ..., callback) { // keep context and BeginGetResponse } 2 void EndGetResponse(...) { // get streamIn and BeginRead } void EndRead(...) { // data read, completed or BeginWrite } void EndWrite(...) { // data wrote, BeginRead }
  • 14. Async 1 IAsyncResult BeginTransfer(url, streamOut, ..., callback) { // keep context and BeginGetResponse } 2 void EndGetResponse(...) { // get streamIn and BeginRead } 3 void EndRead(...) { // data read, completed or BeginWrite } void EndWrite(...) { // data wrote, BeginRead }
  • 15. Async 1 IAsyncResult BeginTransfer(url, streamOut, ..., callback) { // keep context and BeginGetResponse } 2 void EndGetResponse(...) { // get streamIn and BeginRead } 3 void EndRead(...) { // data read, completed or BeginWrite } 4 void EndWrite(...) { // data wrote, BeginRead }
  • 16. Async 1 IAsyncResult BeginTransfer(url, streamOut, ..., callback) { // keep context and BeginGetResponse } 2 void EndGetResponse(...) { // get streamIn and BeginRead } 3 void EndRead(...) { // data read, completed or BeginWrite } 5 4 void EndWrite(...) { // data wrote, BeginRead }
  • 17. Async 1 IAsyncResult BeginTransfer(url, streamOut, ..., callback) { // keep context and BeginGetResponse } 2 void EndGetResponse(...) { // get streamIn and BeginRead } 3 void EndRead(...) { // data read, completed or BeginWrite 6 } 5 4 void EndWrite(...) { // data wrote, BeginRead }
  • 18. Robust & Sync public 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 { // ... } }
  • 19. Robust & Async IAsyncResult BeginTransfer(url, streamOut, ..., callback) { try { ... } catch { ... } } void EndGetResponse(...) { try { ... } catch { ... } } void EndRead(...) { try { ... } catch { ... } } void EndWrite(...) { try { ... } catch { ... } }
  • 20. Event-based Async Model class XxxCompletedEventArgs : EventArgs { Exception Error { get; } TResult Result { get; } } class Worker { event EventHandler<XxxCompletedArgs> XxxCompleted; void XxxAsync(arg1, arg2, ...); }
  • 22. 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
  • 23. .NET 2.0 / C# 2.0
  • 24. “yield” for Iterators IEnumerable<int> Numbers() { yield return 0; yield return 1; yield return 2; }
  • 25. “yield” for Iterators IEnumerable<int> Numbers() { MoveNext() yield return 0; yield return 1; yield return 2; }
  • 26. “yield” for Iterators IEnumerable<int> Numbers() { MoveNext() yield return 0; MoveNext() yield return 1; yield return 2; }
  • 27. “yield” for Iterators IEnumerable<int> Numbers() { MoveNext() yield return 0; MoveNext() yield return 1; MoveNext() yield return 2; }
  • 28. “yield” for Iterators IEnumerable<int> Numbers() { MoveNext() yield return 0; MoveNext() yield return 1; MoveNext() yield return 2; MoveNext() }
  • 29. 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()); } } }
  • 30. 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” after yield return 1; firing async operations 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()); } } }
  • 31. 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” after yield return 1; firing async operations 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()); continue when } async operations } completed }
  • 32. “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
  • 34. 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
  • 35. Concurrency Challenges • Shared State - Immutability • Code Locality - async { ... } • I/O Parallelism - async { ... } • Scaling to Multi-Machine - Agents with async { ... }
  • 36. 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
  • 37. Async Workflow async {   let! res = <async work> ... }
  • 38. Async Workflow React! async {   let! res = <async work> ... }
  • 39. Async Workflow React! async {   let! res = <async work> ... } an HTTP Response an UI Event a Timer Callback a Query Response a Web Servcie Response a Disk I/O Completion an Agent Message
  • 40. 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) }
  • 41. Async in F# let transferAsync (url: string) (streamOut: Stream) = async { let request = WebRequest.Create(url) use! response = request.AsyncGetResponse() AsyncGetResponse let streamIn = response.GetResponseStream() let rec transferDataAsync (buffer: byte[]) = async { let! lengthRead = streamIn.AsyncRead(buffer, 0, buffer.Length) AsyncRead if lengthRead > 0 then do! streamOut.AsyncWrite(buffer, 0, lengthRead) AsyncWrite do! transferDataAsync buffer } simply generate from do! transferDataAsync (Array.zeroCreate 1024) Begin/End methods }
  • 42. How async { ... } Works async { let! img = AsyncRead "http://..." printfn "loaded!" do! AsyncWrite img @"c:..." printfn "saved!" }
  • 43. How async { ... } Works async { 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())))))
  • 44. 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
  • 45. F# Resources http://fsharp.net Programming F# Expert F# 2.0 Real World FP
  • 46. .NET 4.0 / Reactive Framework
  • 47. Reactive Framework Fundamentally change the way you think about coordinating and orchestrating asynchronous and event-based programming
  • 48. How By showing that asynchronous and event-base computations are just push-based collections
  • 49. Interactive Reactive Environment Program
  • 50. Enumerable Collections interface IEnumerable<out T> { IEnumerator<T> GetEnumerator(); } interface IEnumerator<out T> { bool MoveNext(); T Current { get; } }
  • 52. 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); }
  • 53. 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.
  • 54. LINQ to Observable If you are writing LINQ or declarative code in an interactive program...
  • 55. LINQ to Observable If you are writing LINQ or declarative code in an interactive program... You already know how to use it!
  • 56. 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
  • 57. 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
  • 58. Move by WASD // filter the KeyPress events when playing var keyPress = GetKeyPress().Where(_ => isPlaying); // filter the events to move left var 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 top var moveTop = from ev in keyPress where ev.EventArgs.KeyChar == 'w' where ball.Top > 0 select ev; moveTop.Subscribe(_ => ball.Top -= 5);
  • 59. Mouse Drag and Draw var 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));
  • 60. Everything in Web is Asynchronous • User actions • AJAX requests • Animations • ...
  • 61. 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 • ...
  • 62. Drag and Draw in JS var 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); });
  • 63. Wikipedia Lookup var 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); });
  • 64. Time Flies like an Arrow var 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);
  • 65. 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 • ...
  • 66. 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#
  • 67. 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
  • 68. 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/
  • 69. 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.
  • 70. Out of Topic Can we programming like F# in JavaScript?
  • 71. Jscex & Jscex.Async • Computation Expressions and Async Workflow implemented in JavaScript • http://github.com/jeffreyzhao/jscex
  • 72. Clock var drawClockAsync = eval(Jscex.compile("$async", function(interval) { while (true) { drawClock(new Date()); $await(Jscex.Async.sleep(interval)); } } )); Jscex.Async.start(drawClockAsync(1000));
  • 73. Animation var 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)); }));
  • 75. Source 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; }
  • 76. Compiled 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; }
  • 77. Conclusion • Async Programming is difficult • New programming language / feature / library / model can help
  • 78. Q &A