J e f f H a r t
V a n i s h i n g C l o u d s , I n c .
Async/Await for Fun and Profit
Multithreading is just one damn thing after…
…before, or the simultaneously with another.
Scott Meyers and Andrei Alexandrescu
…before
March 19, 2013
Why Multithreading?
 “Modern” apps force multithreading
 Desktop/client – avoiding the “toilet bowl”
 Server-side scalability – all about the cores
 Economics – computers not faster since P4 (90nm)
Copyright © Jeff Hart, 2015
Know Your Goal
 Offloading – free the “main” thread
 Still uses another (Thread Pool) thread
 Works for CPU bound (i.e., thread backed)
 Scaling – not using “any” thread
 Still uses IO completion ports
 Only works for IO bound provided by “framework”
Copyright © Jeff Hart, 2015
Domain: Prime Numbers
 Natural numbers only divisible by itself c and 1
for(int d=2; d<c-1; d++)…
 Only even prime is 2
for(int d=3; d<c-1; d+=2)…
 If c/d = q, then c/q = d; and q or d ≤ SQRT(c)
for(int d=3; d<=Math.Sqrt(c); d+=2)…
 If c/d, then d is a prime or divisible by one<d
So only test against previously found primes
… lots of more powerful sieves
Copyright © Jeff Hart, 2015
First Attempt
Copyright © Jeff Hart, 2015
var nums = Enumerable.Range(1, Math.Sqrt(c));
var query =nums.AsParallel().Where(n => IsPrime(n));
var primes = query.ToArray();
Problems:
 Doesn’t scale (parallel “never” does)
 Doesn’t improve perf on a loaded system
 May not improve perf “anyway”
Which Would You Prefer?
Copyright © Jeff Hart, 2015
(100s)
(100s)
(100s)
(100s)
(100s)
Synchronous
500s elapsed
1 thread
(100s)
(100s)
(100s)
(100s)
(100s)
Parallel
300s elapsed
2 threads
Asynchronous
100.1s elapsed
1 thread
(100s)
(100s)
(100s)
(100s)
(100s)
20ms
Simple Code
Copyright © Jeff Hart, 2015
public async void Click(){
var client = new AsyncSample();
int answer = await client.LongAsync();
txtResult.Text = "Life the universe..."
}
class AsyncSample{
public async Task<int> LongAsync(){
var client = new FrameworkClass();
Task task = client.LongAsync();
…
int result = await task;
…
}
}
CPU Bound IO Bound
Copyright © Jeff Hart, 2015
 Needs “backing” thread
 Parallel.ForEach and
Task.Run
 Unless writing scalable
(server-side) code
 Special advice to “library”
writers (don’t lie/chatty)
 Threads don’t increase
throughput under load
 Doesn’t need/want
 Always use await
rather than another
(background) thread
Ying  Yang
Misconceptions about async/await
Copyright © Jeff Hart, 2015
 async modifier:
 method is async
 await keyword:
 call the async method
and wait until it returns
 suspends the thread
 async modifier:
 method may call async methods/
use await
 await keyword:
 call the async method and return
immediately (assuming it does);
when method completes,
continue from here
 suspends the method (IP)
Basic ROT
 Using await forces signature to: async Task[<T>]
 Warning if async method without using await
 await converts Task<T> to <T> (Task to void)
 Method returns Task<T>, but you return T;
 If you have used await
 Async is cheap—but does allocate; the GC costs
 State machine for method’s local variables
 A delegate
 Task object
Copyright © Jeff Hart, 2015
Rules
Copyright © Jeff Hart, 2015
 Can’t await in catch/finally (C#6/VS15) or lock
 Can’t make properties async
 “Never” call async void (event handlers only)
 Or if you must “fire and forget”
How Sweet the Syntactic Sugar Is
async Task<T> MyMethodAsync(«args»){
var client = …
var r = await client.WhateverAsync(…);
… use r, as needed
return «some expression <T>, i.e., r»;
}
async Task<T> MyMethodAsync(«args»){
var tcs = TaskCompletionSource<T>();
var client = …
client.WhateverAsync(…).ContinueWith(task -> {
var r = task.Result;
… use r, as needed
tcs.SetResult(«some expression <T>, i.e., r»)
});
return tcs.Task;
}
Copyright © Jeff Hart, 2015
Task Class – a Promise…
 ctors – not typically used (takes Action<T>)
 Properties
 Factory, CreationOptions
 IsCanceled, IsCompleted, IsFaulted and Status
 Methods
 Task.Delay – replaces Thread.Sleep
 Task.Run – new in 4.5 (simple sugar)
 FromResult<T>
 ConfigureAwait(bool continueOnCapturedContext)
 ContinueWith…, Wait…, WaitAll…, WaitAny…, Task.Yield
Copyright © Jeff Hart, 2015
Floor to Ceiling
 Go down to:
 Framework XxxAsync for scaling
 “Creating” asynchronicity
Task.Run( { … } ) way better than worker threads
 Go up to:
 Handler
 MSTest, etc.
 Or “eat” the asynchronicity
task.ContinueWith( …, TaskContinuationOptions.Only|Not)
task.Result - blocks
Copyright © Jeff Hart, 2015
We’ve Been At This…
 CLR v1: APM – Async Programming Model
 Simple (mechanical) but limiting
 CLR v2: EAP – Event-based Asynchronous Pattern
 Very flexible but lots of “namespace noise”
 CLR v4: TAP – Task-based Asynchronous Pattern
 V4.5 async/await “complier sugar”
Copyright © Jeff Hart, 2015
Async Programming Model
IAsyncResult BeginDoIt(path,…,
DoitCallback, doItState);
public void DoItCallback(IAsyncResult result){
…
var i = int EndDoIt(result);
}
int DoIt(string path,…); (inputs)
(added—optional)
Options:
1. Block
2. Wait Handle
3. Poll
4. Callback
Interface with
• AsyncState
• AsyncWaitHandle
• IsCompleted
• CompletedSynchronously
Copyright © Jeff Hart, 2015
Event-based Asynchronous Pattern
delegate void DoItCompletedEventHandler(
object sender, DoItCompletedArgs args);
class DoItCompletedArgs :AsyncCompletedEventArgs{
int Result{ get; set; }
}
class MyClass{
void DoItAsync(string path,…);
Event DoItCompletedEventHandler DoItCompleted;
}
Copyright © Jeff Hart, 2015
Task-based Asynchronous Pattern
class MyClass{
async Task<int> DoItAsync(string path,…);
}
Copyright © Jeff Hart, 2015
Transitioning from APM
static Task<int> ToDoItAsync(this MyClass mc
, string path,…)
{
if( mc==null ) throw new ArgumentNullException(…
return Task<int> task = Task.Factory.FromAsync<int>(
mc.BeginDoIt, mc.EndDoIt, path,…);
}
Copyright © Jeff Hart, 2015
Getting Real (Data)
 Entity Framework 6 is TAP enabled
 Secret: using System.Data.Entity;
 All|AnyAsync
 Count|Average|Sum|Min|MaxAsync
 ContainsAsync
 First|Single[OrDefault]Async
 ForEachAsync
 LoadAsync
 ToArray|List|DictionaryAsync
Copyright © Jeff Hart, 2015
Graduation
foreach( var d in GetLotsOfData() ){
DoSomethingReallyLong(d);
}
Parallel.ForEach( GetLotsOfData(), d=>{
DoSomethingReallyLong(d);
}
var tasks = new List<Task>()
foreach( var d in GetLotsOfData() ){
tasks.Add(DoSomethingReallyLongAsync(d));
}
Task.AwaitAll(tasks);
?
Copyright © Jeff Hart, 2015
Layers of Multithreading
 Async/await two-step
 Separating task and await
 Knowin’ when to make ‘em;
And knowin’ when to tend ‘em
 Rules of Thumb
 Mostly compiler enforced/assisted
 Avoid async void (fire and forget)
 Go “floor to ceiling” when possible
 Task’s members to “stop”
 TaskCompletionSource to “create”
The scary bit:
Synchronizing (data)
Copyright © Jeff Hart, 2015
SpeakerRate.com
h t t p : / / s p e a k e r r a t e . c o m / t a l k s / 5 3 5 0 1 - a s y n c - a w a i t - f o r - f u n -
a n d - p r o f i t
S e a r c h f o r “ A s y n c / A w a i t f o r F u n a n d P r o f i t ”
Thank YOU!
Copyright © Jeff Hart, 2015
23

Async await

  • 1.
    J e ff H a r t V a n i s h i n g C l o u d s , I n c . Async/Await for Fun and Profit Multithreading is just one damn thing after… …before, or the simultaneously with another. Scott Meyers and Andrei Alexandrescu …before March 19, 2013
  • 2.
    Why Multithreading?  “Modern”apps force multithreading  Desktop/client – avoiding the “toilet bowl”  Server-side scalability – all about the cores  Economics – computers not faster since P4 (90nm) Copyright © Jeff Hart, 2015
  • 3.
    Know Your Goal Offloading – free the “main” thread  Still uses another (Thread Pool) thread  Works for CPU bound (i.e., thread backed)  Scaling – not using “any” thread  Still uses IO completion ports  Only works for IO bound provided by “framework” Copyright © Jeff Hart, 2015
  • 4.
    Domain: Prime Numbers Natural numbers only divisible by itself c and 1 for(int d=2; d<c-1; d++)…  Only even prime is 2 for(int d=3; d<c-1; d+=2)…  If c/d = q, then c/q = d; and q or d ≤ SQRT(c) for(int d=3; d<=Math.Sqrt(c); d+=2)…  If c/d, then d is a prime or divisible by one<d So only test against previously found primes … lots of more powerful sieves Copyright © Jeff Hart, 2015
  • 5.
    First Attempt Copyright ©Jeff Hart, 2015 var nums = Enumerable.Range(1, Math.Sqrt(c)); var query =nums.AsParallel().Where(n => IsPrime(n)); var primes = query.ToArray(); Problems:  Doesn’t scale (parallel “never” does)  Doesn’t improve perf on a loaded system  May not improve perf “anyway”
  • 6.
    Which Would YouPrefer? Copyright © Jeff Hart, 2015 (100s) (100s) (100s) (100s) (100s) Synchronous 500s elapsed 1 thread (100s) (100s) (100s) (100s) (100s) Parallel 300s elapsed 2 threads Asynchronous 100.1s elapsed 1 thread (100s) (100s) (100s) (100s) (100s) 20ms
  • 7.
    Simple Code Copyright ©Jeff Hart, 2015 public async void Click(){ var client = new AsyncSample(); int answer = await client.LongAsync(); txtResult.Text = "Life the universe..." } class AsyncSample{ public async Task<int> LongAsync(){ var client = new FrameworkClass(); Task task = client.LongAsync(); … int result = await task; … } }
  • 8.
    CPU Bound IOBound Copyright © Jeff Hart, 2015  Needs “backing” thread  Parallel.ForEach and Task.Run  Unless writing scalable (server-side) code  Special advice to “library” writers (don’t lie/chatty)  Threads don’t increase throughput under load  Doesn’t need/want  Always use await rather than another (background) thread Ying  Yang
  • 9.
    Misconceptions about async/await Copyright© Jeff Hart, 2015  async modifier:  method is async  await keyword:  call the async method and wait until it returns  suspends the thread  async modifier:  method may call async methods/ use await  await keyword:  call the async method and return immediately (assuming it does); when method completes, continue from here  suspends the method (IP)
  • 10.
    Basic ROT  Usingawait forces signature to: async Task[<T>]  Warning if async method without using await  await converts Task<T> to <T> (Task to void)  Method returns Task<T>, but you return T;  If you have used await  Async is cheap—but does allocate; the GC costs  State machine for method’s local variables  A delegate  Task object Copyright © Jeff Hart, 2015
  • 11.
    Rules Copyright © JeffHart, 2015  Can’t await in catch/finally (C#6/VS15) or lock  Can’t make properties async  “Never” call async void (event handlers only)  Or if you must “fire and forget”
  • 12.
    How Sweet theSyntactic Sugar Is async Task<T> MyMethodAsync(«args»){ var client = … var r = await client.WhateverAsync(…); … use r, as needed return «some expression <T>, i.e., r»; } async Task<T> MyMethodAsync(«args»){ var tcs = TaskCompletionSource<T>(); var client = … client.WhateverAsync(…).ContinueWith(task -> { var r = task.Result; … use r, as needed tcs.SetResult(«some expression <T>, i.e., r») }); return tcs.Task; } Copyright © Jeff Hart, 2015
  • 13.
    Task Class –a Promise…  ctors – not typically used (takes Action<T>)  Properties  Factory, CreationOptions  IsCanceled, IsCompleted, IsFaulted and Status  Methods  Task.Delay – replaces Thread.Sleep  Task.Run – new in 4.5 (simple sugar)  FromResult<T>  ConfigureAwait(bool continueOnCapturedContext)  ContinueWith…, Wait…, WaitAll…, WaitAny…, Task.Yield Copyright © Jeff Hart, 2015
  • 14.
    Floor to Ceiling Go down to:  Framework XxxAsync for scaling  “Creating” asynchronicity Task.Run( { … } ) way better than worker threads  Go up to:  Handler  MSTest, etc.  Or “eat” the asynchronicity task.ContinueWith( …, TaskContinuationOptions.Only|Not) task.Result - blocks Copyright © Jeff Hart, 2015
  • 15.
    We’ve Been AtThis…  CLR v1: APM – Async Programming Model  Simple (mechanical) but limiting  CLR v2: EAP – Event-based Asynchronous Pattern  Very flexible but lots of “namespace noise”  CLR v4: TAP – Task-based Asynchronous Pattern  V4.5 async/await “complier sugar” Copyright © Jeff Hart, 2015
  • 16.
    Async Programming Model IAsyncResultBeginDoIt(path,…, DoitCallback, doItState); public void DoItCallback(IAsyncResult result){ … var i = int EndDoIt(result); } int DoIt(string path,…); (inputs) (added—optional) Options: 1. Block 2. Wait Handle 3. Poll 4. Callback Interface with • AsyncState • AsyncWaitHandle • IsCompleted • CompletedSynchronously Copyright © Jeff Hart, 2015
  • 17.
    Event-based Asynchronous Pattern delegatevoid DoItCompletedEventHandler( object sender, DoItCompletedArgs args); class DoItCompletedArgs :AsyncCompletedEventArgs{ int Result{ get; set; } } class MyClass{ void DoItAsync(string path,…); Event DoItCompletedEventHandler DoItCompleted; } Copyright © Jeff Hart, 2015
  • 18.
    Task-based Asynchronous Pattern classMyClass{ async Task<int> DoItAsync(string path,…); } Copyright © Jeff Hart, 2015
  • 19.
    Transitioning from APM staticTask<int> ToDoItAsync(this MyClass mc , string path,…) { if( mc==null ) throw new ArgumentNullException(… return Task<int> task = Task.Factory.FromAsync<int>( mc.BeginDoIt, mc.EndDoIt, path,…); } Copyright © Jeff Hart, 2015
  • 20.
    Getting Real (Data) Entity Framework 6 is TAP enabled  Secret: using System.Data.Entity;  All|AnyAsync  Count|Average|Sum|Min|MaxAsync  ContainsAsync  First|Single[OrDefault]Async  ForEachAsync  LoadAsync  ToArray|List|DictionaryAsync Copyright © Jeff Hart, 2015
  • 21.
    Graduation foreach( var din GetLotsOfData() ){ DoSomethingReallyLong(d); } Parallel.ForEach( GetLotsOfData(), d=>{ DoSomethingReallyLong(d); } var tasks = new List<Task>() foreach( var d in GetLotsOfData() ){ tasks.Add(DoSomethingReallyLongAsync(d)); } Task.AwaitAll(tasks); ? Copyright © Jeff Hart, 2015
  • 22.
    Layers of Multithreading Async/await two-step  Separating task and await  Knowin’ when to make ‘em; And knowin’ when to tend ‘em  Rules of Thumb  Mostly compiler enforced/assisted  Avoid async void (fire and forget)  Go “floor to ceiling” when possible  Task’s members to “stop”  TaskCompletionSource to “create” The scary bit: Synchronizing (data) Copyright © Jeff Hart, 2015
  • 23.
    SpeakerRate.com h t tp : / / s p e a k e r r a t e . c o m / t a l k s / 5 3 5 0 1 - a s y n c - a w a i t - f o r - f u n - a n d - p r o f i t S e a r c h f o r “ A s y n c / A w a i t f o r F u n a n d P r o f i t ” Thank YOU! Copyright © Jeff Hart, 2015 23