Marek Safar Engineer Xamarin msafar@xamarin.com Using Async in Your Apps
You?
Wikipedia “Asynchronous events are those occurring independently of the main program flow. Asynchronous actions are actions executed in a non-blocking scheme, allowing the main program flow to continue processing”
You Should Use Async Today • Your UI always remains responsive • No need to guard against race conditions • No ugly callbacks • Compiler does all the heavy li!ing
Async in C# • New major feature of C# 5.0 Makes asynchronous programming a first-class citizen in C# Important part of C# – as significant as LINQ • New async modifier keyword introduced • Methods, lambda expressions, and anonymous methods can be asynchronous • New contextual keyword await introduced
Adding Async to Your Codebase • Decorated with new async modifier • Async method must return one of Task, Task<T> or void type • Async anonymous method and lambdas Delegates returning Task, Task<T> or void • Very few restrictions No ref or out parameters allowed No unsafe code No Main async method No async iterators (aka IAsyncEnumerable<T>)
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 Example: Calculating a Price Asynchronously public  async  Task<int>  CalculatePriceAsync  (Item[]  items) { int  price; //  Calculate  price  asynchronously  and  return  the  value return  price; } public  override  void  ViewDidLoad  () { button.TouchDown  +=  async  (sender,  e)  =>  { //  This  is  asynchronous  handler }; }
Await Introduction • Await can be used in async context only Marks a suspension point Can be used anywhere (except catch and finally blocks) Requires awaitable types (Task, Task<T> but can be any custom type) As many as you like inside async block
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 Calculating a Price Asynchronously public  async  Task<int>  CalculatePriceAsync  (Item[]  items) { using  (var  cmd  =  CreateSqlCommand  (Calculations.TotalPrice,  items))  { using  (var  reader  =  await  cmd.ExecuteReaderAsync  ())  { int  price  =  ReadPrice  (reader); return  price; } } } public  override  void  ViewDidLoad  () { button.TouchDown  +=  async  (sender,  e)  =>  { var  price  =  await  CalculatePriceAsync  (items); priceLabel.Text  =  price.ToString  (); }; }
Cancelling an Async Task • CancellationToken controls cancellation process • Async method needs explicitly support it Usually another method overload Task SaveAsync (CancellationToken token) • Caller calls Cancel on CancellationTokenSource Async method stops and returns Task with cancelled state Implementation detail how quickly async method terminates
DEMO
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 Async Language Features public  async  Task  RealAsync  () { //  This  is  real  async  heavy  code  (only  7  awaits  someone  else  will //  certainly  do  better) var  test  =  new  TestClass  (await  CallAsync  ()  |  await  CallAsync  ())  {   Latitude  =  await  GetLatitudeAsync  (await  AnotherAsync  ()),   Roles  =  from  role  in  await  GetRolesAsync  ()  where  role  ==  "agent"  select  role }; .... test  [await  CallAsync  ()]  =  new  int[]  {  33,  await  GetIntAsync  ()  }; ... }
Best Practices • Use Async naming suffix for asynchronous methods LoadAsync, SendAsync, etc. Only recommended naming convention • Return Task or Task<T> preferably Task for SaveAsync like methods Task<T> for ReadAsync like methods Leave async void to event handlers only • Support cancellation, if possible
Synchronization Context • Framework abstraction over UI toolkit threading model NSRunLoop, DispatchContext in Xamarin.iOS MainLooper in Xamarin.Android Dispatcher in WPF etc. • Await uses synchronization context to restore back suspended context SynchronizationContext::Post method is used Suspension on UI thread resumes back on same UI thread as “expected”
Sometimes Things Go Wrong • Async returning Task or Task<T> Task state is set to Faulted Exception is re-thrown when Task is checked (awaited) • Async void Fire and forget asynchrony Exception is thrown on current synchronization context and your app will crash
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 Exception Handling with Await public  override  void  ViewDidLoad  () { button.TouchDown  +=  async  (sender,  e)  =>  { try  { button.Enabled  =  false; var  price  =  await  CalculatePriceAsync  (items); priceLabel.Text  =  price.ToString  (); }  catch  (Exception  ex)  { //  Handles  price  calculation  error priceLabel.Text  =  "Calculation  failed"; Debug.Print  (ex.ToString  ());  //  Simple  exception  logging }  finally  { button.Enabled  =  true; } }; }
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 Exception Throwing public  async  Task<int>  CalculatePriceAsync  (Item[]  items) { if  (items  ==  null)  { //  Throw  before  suspension throw  new  ArgumentNullException  ("items"); } ... var  price  =  await  CalculatePriceAsync  (items); if  (price  <  0)  { //  Throw  after  suspension throw  new  ArgumentException  ("Invalid  items"); } ... }
Diving Deeper • Await can work with any type which implements the awaiter pattern • Task and Task<T> types do since .NET 4.5 • Any custom type can be made awaitable Has an accessible method called GetAwaiter returning a type which Implements the interface INotifyCompletion Has property IsCompleted of type bool Has method GetResult with no parameters
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 Custom await Behaviour public  async  Task<int>  SomeAsync  () {    ...    await  3000;  //  This  does  not  compile  unless  we  provide  custom  awaiter    ... } //  Name  of  the  method  is  important static  TaskAwaiter  GetAwaiter  (this  int  millisecondsDelay) {    return  Task.Delay  (millisecondsDelay).GetAwaiter  (); }
Async Deadlocks • await restores execution context based on current SynchronizationContext Good for most application code Bad for most library code • Don’t block the UI thread Good old rule still applies in async world Use await when possible
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 Async Deadlock Example public  async  Task<int>  CalculatePriceAsync  (Item[]  items) { using  (var  cmd  =  CreateSqlCommand  (Calculations.TotalPrice,  items))  { using  (var  r  =  await  cmd.ExecuteReaderAsync  ())  { ..... } } } //  The  method  itself  cannot  be  async public  override  bool  FinishedLaunching  (UIApplication  app,  NSDictionary  options) { .... int  price  =  CalculatePriceAsync  (items).Result;    //  Synchronous  wait //  This  line  won’t  be  reached  if  flow  suspension  occurred }
Controlling the Synchronization Context • ConfigureAwait (bool) Controls captured context behaviour • true value - default behaviour Continue execution on context async was called from Important for UI to switch back to UI context • false value Avoids expensive context switching Avoids possible deadlocks on blocking UI
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 Async Deadlock Fixed public  async  Task<int>  CalculatePriceAsync  (Item[]  items) { using  (var  cmd  =  CreateSqlCommand  (Calculations.TotalPrice,  items))  { using  (var  r  =  await  cmd.ExecuteReaderAsync  ().ConfigureAwait  (false))  { //  The  context  is  not  restored  but  that’s  fine  for  no  UI  method   } } } //  The  method  itself  cannot  be  async public  override  bool  FinishedLaunching  (UIApplication  app,  NSDictionary  options) { .... int  price  =  CalculatePriceAsync  (items).Result;    //  Synchronous  wait //  Program  continues  when  the  wait  is  signalled }
Combinators • Asynchronously wait on multiple asynchronous operations Better than individual awaits of multiple tasks The result can be awaited (Task of Tasks) • Task.WhenAll (IEnumerable<Task>) Completes when all of the individual tasks have completed • Task.WhenAny (IEnumerable<Task>) Completes when any of the individual tasks have completed
The Compiler Magic • Compiler does all the “magic” • Local variable and parameters are li!ed into compiler generated type Compiler converts variables and parameters to fields • Any stack values need to be li!ed too Stack needs to be restored a"er suspension • Try-Catch block over any async block • No suspension when awaited task finished
Best Practices - Performance • Use ConfigureAwait when you can • Reduce number of local variables Move async block into separate method or lambda expression Pass variables as parameters Avoid deep await usage • Cache Task not task result • Don’t over use async Use async only when appropriate (unreliable tasks, running >50ms) Async has its own overhead
Get Your Hands on Async • Async is available today Xamarin.iOS Beta release Xamarin.Android Beta release Xamarin Studio async support • Give us feedback on our new async API Forums Bugzilla Mailing list IRC
Q&A
THANK YOU

Using Async in your Mobile Apps - Marek Safar

  • 1.
  • 2.
  • 3.
    Wikipedia “Asynchronous events arethose occurring independently of the main program flow. Asynchronous actions are actions executed in a non-blocking scheme, allowing the main program flow to continue processing”
  • 4.
    You Should UseAsync Today • Your UI always remains responsive • No need to guard against race conditions • No ugly callbacks • Compiler does all the heavy li!ing
  • 6.
    Async in C# •New major feature of C# 5.0 Makes asynchronous programming a first-class citizen in C# Important part of C# – as significant as LINQ • New async modifier keyword introduced • Methods, lambda expressions, and anonymous methods can be asynchronous • New contextual keyword await introduced
  • 7.
    Adding Async toYour Codebase • Decorated with new async modifier • Async method must return one of Task, Task<T> or void type • Async anonymous method and lambdas Delegates returning Task, Task<T> or void • Very few restrictions No ref or out parameters allowed No unsafe code No Main async method No async iterators (aka IAsyncEnumerable<T>)
  • 8.
    01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 Example: Calculating aPrice Asynchronously public  async  Task<int>  CalculatePriceAsync  (Item[]  items) { int  price; //  Calculate  price  asynchronously  and  return  the  value return  price; } public  override  void  ViewDidLoad  () { button.TouchDown  +=  async  (sender,  e)  =>  { //  This  is  asynchronous  handler }; }
  • 9.
    Await Introduction • Awaitcan be used in async context only Marks a suspension point Can be used anywhere (except catch and finally blocks) Requires awaitable types (Task, Task<T> but can be any custom type) As many as you like inside async block
  • 10.
    01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 Calculating a PriceAsynchronously public  async  Task<int>  CalculatePriceAsync  (Item[]  items) { using  (var  cmd  =  CreateSqlCommand  (Calculations.TotalPrice,  items))  { using  (var  reader  =  await  cmd.ExecuteReaderAsync  ())  { int  price  =  ReadPrice  (reader); return  price; } } } public  override  void  ViewDidLoad  () { button.TouchDown  +=  async  (sender,  e)  =>  { var  price  =  await  CalculatePriceAsync  (items); priceLabel.Text  =  price.ToString  (); }; }
  • 11.
    Cancelling an AsyncTask • CancellationToken controls cancellation process • Async method needs explicitly support it Usually another method overload Task SaveAsync (CancellationToken token) • Caller calls Cancel on CancellationTokenSource Async method stops and returns Task with cancelled state Implementation detail how quickly async method terminates
  • 12.
  • 13.
    01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 Async Language Features public  async  Task  RealAsync  () { //  This  is  real  async  heavy  code  (only  7  awaits  someone  else  will //  certainly  do  better) var  test  =  new  TestClass  (await  CallAsync  ()  |  await  CallAsync  ())  {   Latitude  =  await  GetLatitudeAsync  (await  AnotherAsync  ()),   Roles  =  from  role  in  await  GetRolesAsync  ()  where  role  ==  "agent"  select  role }; .... test  [await  CallAsync  ()]  =  new  int[]  {  33,  await  GetIntAsync  ()  }; ... }
  • 14.
    Best Practices • UseAsync naming suffix for asynchronous methods LoadAsync, SendAsync, etc. Only recommended naming convention • Return Task or Task<T> preferably Task for SaveAsync like methods Task<T> for ReadAsync like methods Leave async void to event handlers only • Support cancellation, if possible
  • 15.
    Synchronization Context • Frameworkabstraction over UI toolkit threading model NSRunLoop, DispatchContext in Xamarin.iOS MainLooper in Xamarin.Android Dispatcher in WPF etc. • Await uses synchronization context to restore back suspended context SynchronizationContext::Post method is used Suspension on UI thread resumes back on same UI thread as “expected”
  • 16.
    Sometimes Things GoWrong • Async returning Task or Task<T> Task state is set to Faulted Exception is re-thrown when Task is checked (awaited) • Async void Fire and forget asynchrony Exception is thrown on current synchronization context and your app will crash
  • 17.
    01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 Exception Handling withAwait public  override  void  ViewDidLoad  () { button.TouchDown  +=  async  (sender,  e)  =>  { try  { button.Enabled  =  false; var  price  =  await  CalculatePriceAsync  (items); priceLabel.Text  =  price.ToString  (); }  catch  (Exception  ex)  { //  Handles  price  calculation  error priceLabel.Text  =  "Calculation  failed"; Debug.Print  (ex.ToString  ());  //  Simple  exception  logging }  finally  { button.Enabled  =  true; } }; }
  • 18.
    01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 Exception Throwing public  async  Task<int>  CalculatePriceAsync  (Item[]  items) { if  (items  ==  null)  { //  Throw  before  suspension throw  new  ArgumentNullException  ("items"); } ... var  price  =  await  CalculatePriceAsync  (items); if  (price  <  0)  { //  Throw  after  suspension throw  new  ArgumentException  ("Invalid  items"); } ... }
  • 19.
    Diving Deeper • Awaitcan work with any type which implements the awaiter pattern • Task and Task<T> types do since .NET 4.5 • Any custom type can be made awaitable Has an accessible method called GetAwaiter returning a type which Implements the interface INotifyCompletion Has property IsCompleted of type bool Has method GetResult with no parameters
  • 20.
    01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 Custom await Behaviour public  async  Task<int>  SomeAsync  () {    ...    await  3000;  //  This  does  not  compile  unless  we  provide  custom  awaiter    ... } //  Name  of  the  method  is  important static  TaskAwaiter  GetAwaiter  (this  int  millisecondsDelay) {    return  Task.Delay  (millisecondsDelay).GetAwaiter  (); }
  • 21.
    Async Deadlocks • awaitrestores execution context based on current SynchronizationContext Good for most application code Bad for most library code • Don’t block the UI thread Good old rule still applies in async world Use await when possible
  • 22.
    01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 Async Deadlock Example public  async  Task<int>  CalculatePriceAsync  (Item[]  items) { using  (var  cmd  =  CreateSqlCommand  (Calculations.TotalPrice,  items))  { using  (var  r  =  await  cmd.ExecuteReaderAsync  ())  { ..... } } } //  The  method  itself  cannot  be  async public  override  bool  FinishedLaunching  (UIApplication  app,  NSDictionary  options) { .... int  price  =  CalculatePriceAsync  (items).Result;    //  Synchronous  wait //  This  line  won’t  be  reached  if  flow  suspension  occurred }
  • 23.
    Controlling the SynchronizationContext • ConfigureAwait (bool) Controls captured context behaviour • true value - default behaviour Continue execution on context async was called from Important for UI to switch back to UI context • false value Avoids expensive context switching Avoids possible deadlocks on blocking UI
  • 24.
    01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 Async Deadlock Fixed public  async  Task<int>  CalculatePriceAsync  (Item[]  items) { using  (var  cmd  =  CreateSqlCommand  (Calculations.TotalPrice,  items))  { using  (var  r  =  await  cmd.ExecuteReaderAsync  ().ConfigureAwait  (false))  { //  The  context  is  not  restored  but  that’s  fine  for  no  UI  method   } } } //  The  method  itself  cannot  be  async public  override  bool  FinishedLaunching  (UIApplication  app,  NSDictionary  options) { .... int  price  =  CalculatePriceAsync  (items).Result;    //  Synchronous  wait //  Program  continues  when  the  wait  is  signalled }
  • 25.
    Combinators • Asynchronously waiton multiple asynchronous operations Better than individual awaits of multiple tasks The result can be awaited (Task of Tasks) • Task.WhenAll (IEnumerable<Task>) Completes when all of the individual tasks have completed • Task.WhenAny (IEnumerable<Task>) Completes when any of the individual tasks have completed
  • 26.
    The Compiler Magic •Compiler does all the “magic” • Local variable and parameters are li!ed into compiler generated type Compiler converts variables and parameters to fields • Any stack values need to be li!ed too Stack needs to be restored a"er suspension • Try-Catch block over any async block • No suspension when awaited task finished
  • 27.
    Best Practices -Performance • Use ConfigureAwait when you can • Reduce number of local variables Move async block into separate method or lambda expression Pass variables as parameters Avoid deep await usage • Cache Task not task result • Don’t over use async Use async only when appropriate (unreliable tasks, running >50ms) Async has its own overhead
  • 28.
    Get Your Handson Async • Async is available today Xamarin.iOS Beta release Xamarin.Android Beta release Xamarin Studio async support • Give us feedback on our new async API Forums Bugzilla Mailing list IRC
  • 29.
  • 30.