Date post: | 16-Dec-2015 |
Category: |
Documents |
Upload: | ashley-johnston |
View: | 215 times |
Download: | 0 times |
“I love magic, as long as I understand how it works”
- Jon Skeet, 2013
“Any sufficiently advanced technology is indistinguishable
from magic”- Arthur C. Clarke, 1961
TodayOverviewWhy do we need asynchronous programming?Async in C#
Let’s build itWhy not?
Practical async6 tips you should know
You are in a dark room with no signs of life. You still have your torch and $356.
You can go North (N) or South (S).
Your choice? _
Approach 1: Blockingvoid ServeCustomer(Customer customer){ var order = TakeOrder(customer);
// blocking call var pizza = GetSomeoneToMakeThePizza(order);
GivePizzaToCustomer(customer, pizza); WaitForCustomerToFinishEating();
CleanUpCustomerRubbish();}
Blocking can be dangerousWhen we have scarce resources (threads)UI threadsJavascriptI/O
When resources are too expensive~1MB per thread memory usageThreads are only added to the ThreadPool slowly
When we have too many processes to coordinate‘Duplex’ connections – long running process per user
Approach 2: Callbacksvoid ServeCustomer(Customer customer){ var order = TakeOrder(customer);
var cook = new Cook(); cook.PizzaFinished += (pizza) => { customer.FinishedEating += CleanUpCustomerRubbish;
GivePizzaToCustomer(customer, pizza); };
cook.GetSomeoneToMakeThePizza(order); // How do we return a value from the method?}
Approach 3: Promisesvoid ServeCustomer(Customer customer){ var order = TakeOrder(customer);
GetSomeoneToMakeThePizza(order) .ContinueWith(pizzaTask => { GivePizzaToCustomer(customer, pizza); return WaitForCustomerToFinishEating(); }) .ContinueWith(task => { CleanUpCustomerRubbish(); });}
C# async awaitasync void ServeCustomer(Customer customer){ var order = TakeOrder(customer);
var pizza = await GetSomeoneToMakeThePizza(order);
GivePizzaToCustomer(customer, pizza); await WaitForCustomerToFinishEating();
CleanUpCustomerRubbish();}
C# async awaitasync void ServeCustomer(Customer customer){ var order = TakeOrder(customer); try { var pizza = await GetSomeoneToMakeThePizza(order); GivePizzaToCustomer(customer, pizza); using (var employee = GetNewEmployee()) { await WaitForCustomerToFinishEating(); employee.CleanUpCustomerRubbish(); } } catch (PizzaMakingException ex) { }}
Task PlayersTasksThe results or promise of a result from asynchronous methods
AwaitersHolds a collection of continuations, TaskAdapter<T> acts as adapter for a Task<T>
MethodBuilderCoordinates the running of an async method
ContinuationsWhat do I run when the task is finished?
SchedulersHow do I run the continuation?
Use TaskCompletionSource to create your own Tasks Task<Pizza> CookPizzaAsync(Order order){ var taskCompletion = new TaskCompletionSource<Pizza>();
var cook = new Cook(); cook.PizzaCompleted += (pizza) => { taskCompletion.SetResult(pizza); };
cook.MakePizza(order);
return taskCompletion.Task;}
Wrap business process in Tasks
async Task SpeakAtTechEd(){ SubmitTopics();
var acceptedTalks = await WaitToHearIfAcceptedAsync(); var slides = await Task.WhenAll( acceptedTalks.Select( talk => PrepareTalkAsync(talk) ) );
DeliverTalks(slides);}
Make sure all Tasks are observed
void OnButtonClick(){ var customer = MeetNewCustomer(); // don’t do this. Make ServeCustomerAsync async void, or await it ServeCustomerAsync(customer);}
async Task ServeCustomerAsync(Customer customer){ ...}
Be careful with async void
void OnButtonClick(){ var customer = MeetNewCustomer(); ServeCustomerAsync(customer);
// Customers may or may not still be eating… and we can’t catch Exceptions WashDishes();}
async void ServeCustomerAsync(Customer customer){ ...}
Use ConfigureAwait(false) when possible
async Task PushDataAsync(){ var customer = await GetCustomerAsync() .ConfigureAwait(false);
await UpdateDatabaseAsync() .ConfigureAwait(false);
await PushDataToServiceAsync() .ConfigureAwait(false);}
Async void can still be unit tested
[TestMethod]public async Task SimpleAsyncVoidExample(){ var customer = new Customer(); // async void methods UpdateFirstName(customer); UpdateLastName(customer); // Override the SynchronizationContext // Utilise the OperationStarted and OperationCompleted overrides await TaskTrackingSynchronizationContext.WaitForAsync(); Assert.AreEqual("Bob", customer.FirstName); Assert.AreEqual("Jones", customer.LastName);}
Related contentBreakout Sessions
DEV414: Taming Time: A Deep Dive into the Reactive Extensions
Linkshttp://blogs.msdn.com/b/pfxteam/http://msmvps.com/blogs/jon_skeet/archive/tags/Eduasync/default.aspx
Contact me later…During drinksTwitter: @kiwidevEmail: [email protected]
© 2013 Microsoft Corporation. All rights reserved.Microsoft, Windows and other product names are or may be registered trademarks and/or trademarks in the U.S. and/or other countries.MICROSOFT MAKES NO WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, AS TO THE INFORMATION IN THIS PRESENTATION.
Async comes in many flavours.NET 4.5.NET 4 (with BCL.Core.Async)PCLXamarin
Javascript (ES6 generators)Currently in Firefox and node.js
Yieldvoid CallYield(){ int callIndex = 0; Console.WriteLine(“ Call - 1"); foreach (var number in GetNumbers()) { Console.WriteLine(" Call: " + callIndex++); }}
IEnumerable<int> GetNumbers(){ Console.WriteLine("Before 1"); yield return 1;
Console.WriteLine("Before 2"); yield return 2;
Console.WriteLine("Yield finished");}
Call - 1Before 1 Call: 0Before 2 Call: 1Yield finished Call: 2