45
Demystifying the .NET Asynchronous Programming Landscape Bart J.F. De Smet blogs.bartdesmet.net/bart [email protected]

Demystifying the .NET Asynchronous Programming Landscape

Embed Size (px)

DESCRIPTION

Demystifying the .NET Asynchronous Programming Landscape. Bart J.F. De Smet blogs.bartdesmet.net/bart [email protected]. It’s All About Time!. What’s asynchrony ? Greek origin a (not) syn (together with) chronos (time) Multiple parties evolving in time independently - PowerPoint PPT Presentation

Citation preview

Demystifying the .NET Asynchronous Programming LandscapeBart J.F. De Smetblogs.bartdesmet.net/[email protected]

It’s All About Time!

• What’s asynchrony?• Greek origin• a (not)• syn (together with)• chronos (time)

• Multiple parties evolving in time independently• Not being blocked

• Related concepts• Concurrency• Order in which multiple tasks execute is not determined

• Parallelism• True simultaneous execution (e.g. multicore)

It’s a Jungle Out There!

Your Program Here

Eventstriggered

I/O

completed

Packet

received

EventsCallbacks

Reactive

Nobody Likes to be Blocked

• A connected world with I/O• Network sockets• Web services• Instant messaging

• Don’t block the UI thread!• PostMessage• Control.Invoke• Dispatcher.BeginInvoke

• Asynchrony in frameworks• Silverlight• Windows Phone 7• AJAX

Language support?

From the Bottom UpHardware based on

asynchrony…

Programming model?

Abstractions in the .NET Framework

using System;using System.IO;

class Program{ static void Main() { var buffer = new byte[4 * 1024 * 1024 /* 4MB */];

using (var fs = File.OpenRead(@“c:\temp\sample.big”)) { fs.BeginRead(buffer, 0, buffer.Length, iar => { // Process results in buffer }, null); } }}

Spot the defects

Callback using a lambda expression

Lack of closures in C# 1.0

Lifetime issues?

Need EndRead?

Abstractions in the .NET Framework

• Asynchronous Methods

• Event-Based Asynchronous Pattern

• BackgroundWorker Component

IAsyncResult BeginRead(…, AsyncCallback callback, object state);int EndRead(IAsyncResult result);

void DownloadAsync(…);event DownloadCompletedEventHandler DownloadCompleted;

void RunWorkerAsync();void ReportProgress(int percentProgress);

event DoWorkEventHandler DoWork;event ProgressChangedEventHandler ProgressChanged;event RunWorkerCompletedEventHandler RunWorkerCompleted;

Asynchronous is not unlike event-driven

Use of callback functions

DEMOAsynchronous Methods in .NET

The Task Parallel Library in .NET 4

Can you keep the cores busy?

Gordon Moore

True parallelism has become reality

Essential TPL Concepts – Task<T>

• Representation of a computation• Also known as a “future”

• Cheaper than threads• Continuations can be hooked up• Also known as “continuation passing style” (CPS)

Task<int> x = Task<int>.Factory.StartNew(() => { // (Long-running) computation of the result.});

x.ContinueWith(x2 => { // Code for the continuation after x completes, // with x2 an alias for the original task.});

Your application logic ends up inside out

Code runs on the CLR’s task pool

Continuations allow for sequencing

Continuations for Dummies

var report = Task.Factory.StartNew(() => GetFileData())

Returns abyte[]

.ContinueWith(x => Analyze(x.Result))

Receives aTask<byte[]>

.ContinueWith(y => Summarize(y.Result));

Data available in byte[]

What about errors? Returns a

double[]Receives a

Task<double[]>

Data Flow

Pipeline

DEMOWorking with Task<T> in .NET 4

Language Support for Asynchronous Programming – F#

13

let processAsync i = async { use stream = File.OpenRead(sprintf "Image%d.tmp" i) let! pixels = stream.AsyncRead(numPixels) let pixels' = transform pixels i use out = File.OpenWrite(sprintf "Image%d.done" i) do! out.AsyncWrite(pixels') }

let processAsyncDemo = printfn "async demo..." let tasks = [ for i in 1 .. numImages -> processAsync i ] Async.RunSynchronously (Async.Parallel tasks) |> ignore printfn "Done!"

stream.Read(numPixels, pixels -> let pixels' = transform pixels i use out = File.OpenWrite(sprintf "Image%d.done" i) do! out.AsyncWrite(pixels'))

Com

pile

r

Tran

sform

ation

(Asynchronous) Workflows in F#

• General-purpose language feature introduced by F#• Based on theory of monads• More exhaustive compared to LINQ in C# and VB• Overloadable meaning for specific keywords

• Continuation passing style• Synchronous: ‘a -> ‘b• Asynchronous:‘a -> (‘b -> unit) -> unit• In C# style: Action<T, Action<R>>

• Core concept: async { /* code */ }• Syntactic sugar for keywords inside block• E.g. let!, do!, use!

Continuation function receives result (~ ContinueWith)

DEMOAsynchronous Workflows in F#

Introducing the Visual Studio Async CTP

16

PDC 2010

Asynchronous Control Flow

async void DoWorkAsync() { var t1 = ProcessFeedAsync("www.acme.com/rss"); var t2 = ProcessFeedAsync("www.xyznews.com/rss"); await Task.WhenAll(t1, t2); DisplayMessage("Done");}

async Task ProcessFeedAsync(string url) { var text = await DownloadFeedAsync(url); var doc = ParseFeedIntoDoc(text); await SaveDocAsync(doc); ProcessLog.WriteEntry(url);}

UI Thread

Message Pump

Asynchronous Control Flow

async void DoWorkAsync() { var t1 = ProcessFeedAsync("www.acme.com/rss"); var t2 = ProcessFeedAsync("www.xyznews.com/rss"); await Task.WhenAll(t1, t2); DisplayMessage("Done");}

async Task ProcessFeedAsync(string url) { var text = await DownloadFeedAsync(url); var doc = ParseFeedIntoDoc(text); await SaveDocAsync(doc); ProcessLog.WriteEntry(url);}

Asynchronous Control Flow

async void DoWorkAsync() { var t1 = ProcessFeedAsync("www.acme.com/rss"); var t2 = ProcessFeedAsync("www.xyznews.com/rss"); await Task.WhenAll(t1, t2); DisplayMessage("Done");}

async Task ProcessFeedAsync(string url) { var text = await DownloadFeedAsync(url); var doc = ParseFeedIntoDoc(text); await SaveDocAsync(doc); ProcessLog.WriteEntry(url);}

Asynchronous Control Flow

async void DoWorkAsync() { var t1 = ProcessFeedAsync("www.acme.com/rss"); var t2 = ProcessFeedAsync("www.xyznews.com/rss"); await Task.WhenAll(t1, t2); DisplayMessage("Done");}

async Task ProcessFeedAsync(string url) { var text = await DownloadFeedAsync(url); var doc = ParseFeedIntoDoc(text); await SaveDocAsync(doc); ProcessLog.WriteEntry(url);}

Asynchronous Control Flow

async void DoWorkAsync() { var t1 = ProcessFeedAsync("www.acme.com/rss"); var t2 = ProcessFeedAsync("www.xyznews.com/rss"); await Task.WhenAll(t1, t2); DisplayMessage("Done");}

async Task ProcessFeedAsync(string url) { var text = await DownloadFeedAsync(url); var doc = ParseFeedIntoDoc(text); await SaveDocAsync(doc); ProcessLog.WriteEntry(url);}

t1

Asynchronous Control Flow

async void DoWorkAsync() { var t1 = ProcessFeedAsync("www.acme.com/rss"); var t2 = ProcessFeedAsync("www.xyznews.com/rss"); await Task.WhenAll(t1, t2); DisplayMessage("Done");}

async Task ProcessFeedAsync(string url) { var text = await DownloadFeedAsync(url); var doc = ParseFeedIntoDoc(text); await SaveDocAsync(doc); ProcessLog.WriteEntry(url);}

t1

t2

Asynchronous Control Flow

async void DoWorkAsync() { var t1 = ProcessFeedAsync("www.acme.com/rss"); var t2 = ProcessFeedAsync("www.xyznews.com/rss"); await Task.WhenAll(t1, t2); DisplayMessage("Done");}

async Task ProcessFeedAsync(string url) { var text = await DownloadFeedAsync(url); var doc = ParseFeedIntoDoc(text); await SaveDocAsync(doc); ProcessLog.WriteEntry(url);}

t1

t2

Asynchronous Control Flow

async void DoWorkAsync() { var t1 = ProcessFeedAsync("www.acme.com/rss"); var t2 = ProcessFeedAsync("www.xyznews.com/rss"); await Task.WhenAll(t1, t2); DisplayMessage("Done");}

async Task ProcessFeedAsync(string url) { var text = await DownloadFeedAsync(url); var doc = ParseFeedIntoDoc(text); await SaveDocAsync(doc); ProcessLog.WriteEntry(url);}

t1

t2

Asynchronous Control Flow

async void DoWorkAsync() { var t1 = ProcessFeedAsync("www.acme.com/rss"); var t2 = ProcessFeedAsync("www.xyznews.com/rss"); await Task.WhenAll(t1, t2); DisplayMessage("Done");}

async Task ProcessFeedAsync(string url) { var text = await DownloadFeedAsync(url); var doc = ParseFeedIntoDoc(text); await SaveDocAsync(doc); ProcessLog.WriteEntry(url);}

t1

t2

Asynchronous Control Flow

async void DoWorkAsync() { var t1 = ProcessFeedAsync("www.acme.com/rss"); var t2 = ProcessFeedAsync("www.xyznews.com/rss"); await Task.WhenAll(t1, t2); DisplayMessage("Done");}

async Task ProcessFeedAsync(string url) { var text = await DownloadFeedAsync(url); var doc = ParseFeedIntoDoc(text); await SaveDocAsync(doc); ProcessLog.WriteEntry(url);}

t1

t2

Asynchronous Control Flow

async void DoWorkAsync() { var t1 = ProcessFeedAsync("www.acme.com/rss"); var t2 = ProcessFeedAsync("www.xyznews.com/rss"); await Task.WhenAll(t1, t2); DisplayMessage("Done");}

async Task ProcessFeedAsync(string url) { var text = await DownloadFeedAsync(url); var doc = ParseFeedIntoDoc(text); await SaveDocAsync(doc); ProcessLog.WriteEntry(url);}

t1

t2

Asynchronous Control Flow

async void DoWorkAsync() { var t1 = ProcessFeedAsync("www.acme.com/rss"); var t2 = ProcessFeedAsync("www.xyznews.com/rss"); await Task.WhenAll(t1, t2); DisplayMessage("Done");}

async Task ProcessFeedAsync(string url) { var text = await DownloadFeedAsync(url); var doc = ParseFeedIntoDoc(text); await SaveDocAsync(doc); ProcessLog.WriteEntry(url);}

t1

t2

Asynchronous Control Flow

async void DoWorkAsync() { var t1 = ProcessFeedAsync("www.acme.com/rss"); var t2 = ProcessFeedAsync("www.xyznews.com/rss"); await Task.WhenAll(t1, t2); DisplayMessage("Done");}

async Task ProcessFeedAsync(string url) { var text = await DownloadFeedAsync(url); var doc = ParseFeedIntoDoc(text); await SaveDocAsync(doc); ProcessLog.WriteEntry(url);}

t1

t2

Asynchronous Control Flow

async void DoWorkAsync() { var t1 = ProcessFeedAsync("www.acme.com/rss"); var t2 = ProcessFeedAsync("www.xyznews.com/rss"); await Task.WhenAll(t1, t2); DisplayMessage("Done");}

async Task ProcessFeedAsync(string url) { var text = await DownloadFeedAsync(url); var doc = ParseFeedIntoDoc(text); await SaveDocAsync(doc); ProcessLog.WriteEntry(url);}

t1

t2

Asynchronous Control Flow

async void DoWorkAsync() { var t1 = ProcessFeedAsync("www.acme.com/rss"); var t2 = ProcessFeedAsync("www.xyznews.com/rss"); await Task.WhenAll(t1, t2); DisplayMessage("Done");}

async Task ProcessFeedAsync(string url) { var text = await DownloadFeedAsync(url); var doc = ParseFeedIntoDoc(text); await SaveDocAsync(doc); ProcessLog.WriteEntry(url);}

t1

t2

Asynchronous Control Flow

async void DoWorkAsync() { var t1 = ProcessFeedAsync("www.acme.com/rss"); var t2 = ProcessFeedAsync("www.xyznews.com/rss"); await Task.WhenAll(t1, t2); DisplayMessage("Done");}

async Task ProcessFeedAsync(string url) { var text = await DownloadFeedAsync(url); var doc = ParseFeedIntoDoc(text); await SaveDocAsync(doc); ProcessLog.WriteEntry(url);}

t1

t2

Asynchronous Control Flow

async void DoWorkAsync() { var t1 = ProcessFeedAsync("www.acme.com/rss"); var t2 = ProcessFeedAsync("www.xyznews.com/rss"); await Task.WhenAll(t1, t2); DisplayMessage("Done");}

async Task ProcessFeedAsync(string url) { var text = await DownloadFeedAsync(url); var doc = ParseFeedIntoDoc(text); await SaveDocAsync(doc); ProcessLog.WriteEntry(url);}

t1

t2

DEMOVisual Studio Async CTP

Events Are All Around Us

Socialmedia

Stock tickers

RSS feeds

GPS

Server managementUI e

vents

Event Processing Systems

Rx is a library for composing asynchronous

and event-based programs using observable

sequences.

( 𝑓 ◦𝑔)(𝑥 )= 𝑓 (𝑔(𝑥 ))

Queries! LINQ!

Way simpler with Rx

• .NET 3.5 SP1 and 4.0• Silverlight 3, 4, and 5• XNA 4.0 for Xbox 360• Windows Phone 7• JavaScript (RxJS)

Download at MSDN Data Developer Center or use NuGet

Environment

Mov

eNex

tGot next?

Application

OnN

ext Have next!

IEnumerable<T>IEnumerator<T>

IObservable<T>IObserver<T>

Inte

racti

ve ReactivePush-Based Data Retrieval

Event Programming Interfaces

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

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

Both interfaces ship in the .NET 4 BCL

Observers used to define callbacks

In today’s word, errors are a given

Writing Rx Queries over Event Streams

// IObservable<string> from TextChanged eventsvar changed = Observable.FromEventPattern(txt, "TextChanged");var input = (from text in changed select ((TextBox)text.Sender).Text); .DistinctUntilChanged() .Throttle(TimeSpan.FromSeconds(1));

// Bridge with the dictionary web servicevar svc = new DictServiceSoapClient();var lookup = Observable.FromAsyncPattern<string, DictionaryWord[]> (svc.BeginLookup, svc.EndLookup);

// Retrieve results and hop from stream to streamvar res = (from term in input select lookup(term)) .Switch();

Importing .NET events as observables

Bridging the async method pattern

One stream per web service request

DEMOEvent Processing with Rx

Asynchronous Data Processing Overview

#

Synchronous Asynchronous

Sing

le v

alue

(1)

Mul

tiple

val

ues

(*)

Func<T> Task<T>

IEnumerable<T> IObservable<T>

y = f(x); y = await g(x);

Invocation expressions Await expressions

Sequencing through statements

res = from x in xs from y in q(x) …;

Composition on query expressions

foreach (var z in res) …

res.Subscribe(x => …

Imperative style code

Functional style code

Summary

• Asynchrony is everywhere• Emergence of async-only APIs• Windows Phone, Silverlight, JavaScript

• Don’t block the UI• Have to deal with latency

• Call to action• Learn about Task<T>• Download the Async CTP• http://msdn.com/vstudio/async

• Download Reactive Extensions (Rx)• http://msdn.com/data/gg577609

Stay up to date with MSDN Belux

• Register for our newsletters and stay up to date:http://www.msdn-newsletters.be• Technical updates• Event announcements and registration• Top downloads

• Follow our bloghttp://blogs.msdn.com/belux

• Join us on Facebookhttp://www.facebook.com/msdnbehttp://www.facebook.com/msdnbelux

• LinkedIn: http://linkd.in/msdnbelux/ • Twitter: @msdnbelux

Download MSDN/TechNet Desktop Gadget

http://bit.ly/msdntngadget

TechDays 2011 On-Demand

• Watch this session on-demand via Channel9http://channel9.msdn.com/belux

• Download to your favorite MP3 or video player• Get access to slides and recommended resources by the speakers

THANK YOU