Se ha denunciado esta presentación.
Utilizamos tu perfil de LinkedIn y tus datos de actividad para personalizar los anuncios y mostrarte publicidad más relevante. Puedes cambiar tus preferencias de publicidad en cualquier momento.
Lluis Franco & Alex Casquete
.NET Conference 2015
Y
A
X B
Evolution of the async model
Async void is only for top-level event handlers.
Use the threadpool for CPU-bound code, but n...
ayudarte con algo
It seems you’re calling an async
method without awaiting…
Can I help you?
Yep! Return a Task object plz
...
private async void Button1_Click(object Sender, EventArgs e) {
Thread oThread = new Thread(new ThreadStart(myExpensiveMeth...
private async void Button1_Click(object Sender, EventArgs e) {
//Thread oThread = new Thread(new ThreadStart(myExpensiveMe...
private int myExpensiveMethod()
{
...
return 42;
}
private void Button1_Click(object sender, EventArgs e)
{
var function =...
var numbers = Enumerable.Range(1, 10000000);
var query = numbers.AsParallel().Where(n => n.IsPrime());
var primes = query....
var customers = Customer.GetSampleCustomers();
Parallel.ForEach(customers, c => {
if(!c.IsActive) c.Balance = 0;
});
public static List<string> GetNetworkSQLServerInstances() {
//Get local network servers
return servers;
}
private void upd...
public static List<string> GetNetworkSQLServerInstances() {
//Get local network servers
return servers;
}
private void upd...
public static List<string> GetNetworkSQLServerInstances() {
//Get local network servers
return servers;
}
private void upd...
public static List<string> GetNetworkSQLServerInstances() {
//Get local network servers
return servers;
}
private void upd...
public static Task<List<string>> GetNetworkSQLServerInstancesAsync() {
//Get local network servers
return servers;
}
//ASY...




//ASYNC/AWAIT version
private async void Button1_Click(object sender, EventArgs e) {
var servers = await GetNetwor...
public static void SimpleBody() {
Console.WriteLine("Hello, Async World!");
}
.method public hidebysig static void SimpleB...
public static async Task SimpleBody() {
Console.WriteLine("Hello, Async World!");
}
.method public hidebysig static class ...
private async void Button1_Click(object Sender, EventArgs e) {
try {
SendData("https://secure.flickr.com/services/oauth/re...
private async void Button1_Click(object Sender, EventArgs e) {
try {
SendData("https://secure.flickr.com/services/oauth/re...
private async void Button1_Click(object Sender, EventArgs e) {
try {
SendData("https://secure.flickr.com/services/oauth/re...
// Q. It sometimes shows PixelWidth and PixelHeight are both 0 ???
BitmapImage m_bmp;
protected override async void OnNavi...
// A. Use a task
Task<BitmapImage> m_bmpTask;
protected override async void OnNavigatedTo(NavigationEventArgs e) {
base.On...
' In VB, the expression itself determines void- or Task-returning (not the context).
Dim void_returning = Async Sub()
Awai...
// table1.DataSource = LoadHousesSequentially(1,5);
// table1.DataBind();
public List<House> LoadHousesSequentially(int fi...
// table1.DataSource = LoadHousesInParallel(1,5);
// table1.DataBind();
public List<House> LoadHousesInParallel(int first,...
end1
start1
end2
start2
end3
start3
end4
start4
end5
start5
3end3
start3
end1
start1
end2
start2
end5
start5
response out
~200ms
Parallel.For
end3
start3
end4
start4
end2
start1
start2
start3
start4
start5
response out
~100ms
end5
end1
end3
end4
// table1.DataSource = await LoadHousesAsync(1,5);
// table1.DataBind();
public async Task<List<House>> LoadHousesAsync(in...
public async void btnPayout_Click(object sender, RoutedEventArgs e)
{
double initialPrice, strikePrice, drift, volatility ...
public async void btnPayout_Click(object sender, RoutedEventArgs e)
{
double initialPrice, strikePrice, drift, volatility ...
public async void btnPayout_Click(object sender, RoutedEventArgs e)
{
double initialPrice, strikePrice, drift, volatility ...
Foo();
var task = FooAsync();
...
await task;
synchronous
perform
when it’s done
asynchronous
initiate
immediately
public static void PausePrint2() {
Task t = PausePrintAsync();
t.Wait();
}
// “I’m not allowed an async signature,
// but ...
The threadpool is an app-global resource
In a server app, spinning up threads hurts scalability
The app is in the best pos...
async Task LoadAsync() {
await IO.Network.DownloadAsync(path);
}
void Button1_Click(){
var t = LoadAsync();
t.Wait();
Upda...
server scalability.
We all know sync methods are “cheap”
public static void SimpleBody() {
Console.WriteLine("Hello, Async World!");
}
.method...
Not so for asynchronous methods
public static async Task SimpleBody() {
Console.WriteLine("Hello, Async World!");
}
.metho...
public static async Task<int> GetNextIntAsync()
{
if (m_Count == m_Buf.Length)
{
m_Buf = await FetchNextBufferAsync();
m_C...
var x = await GetNextIntAsync(); var $awaiter = GetNextIntAsync().GetAwaiter();
if (!$awaiter.IsCompleted) {
DO THE AWAIT/...
public static async Task<int> GetNextIntAsync()
{
if (m_Count == m_Buf.Length)
{
m_Buf = await FetchNextBufferAsync();
m_C...
The heap is an app-global resource.
Like all heap allocations, async allocations can contributing to hurting GC perf.
Sync context represents a “target for work”
“Await task” uses the sync context
“where you were before”
But for library cod...
UI responsiveness
Lluis Franco & Alex Casquete
Async best practices
¡¡¡Si te ha gustado no olvides
rellenar la encuesta!!!
Thanks
Y
A
X B
Async Best Practices
Async Best Practices
Async Best Practices
Async Best Practices
Async Best Practices
Async Best Practices
Async Best Practices
Async Best Practices
Async Best Practices
Async Best Practices
Async Best Practices
Async Best Practices
Async Best Practices
Async Best Practices
Async Best Practices
Async Best Practices
Async Best Practices
Async Best Practices
Async Best Practices
Próxima SlideShare
Cargando en…5
×

Async Best Practices

3.512 visualizaciones

Publicado el

Async Best Practices Speech @ DotNet Spain Conference 2015

Publicado en: Tecnología
  • Sé el primero en comentar

Async Best Practices

  1. 1. Lluis Franco & Alex Casquete .NET Conference 2015 Y A X B
  2. 2. Evolution of the async model Async void is only for top-level event handlers. Use the threadpool for CPU-bound code, but not IO-bound. Libraries shouldn't lie, and should be chunky. Micro-optimizations: Consider ConfigureAwait(false)
  3. 3. ayudarte con algo It seems you’re calling an async method without awaiting… Can I help you? Yep! Return a Task object plz Nope. Maybe latter.
  4. 4. private async void Button1_Click(object Sender, EventArgs e) { Thread oThread = new Thread(new ThreadStart(myExpensiveMethod)); oThread.Start(); ... oThread.Abort(); ... if(oThread.IsAlive) { ... } } private static void myExpensiveMethod() { //Some expensive stuff here... //Read from Database/Internet //Perform some calculations salaryTextBox.Text = result; }
  5. 5. private async void Button1_Click(object Sender, EventArgs e) { //Thread oThread = new Thread(new ThreadStart(myExpensiveMethod)); //oThread.Start(); ThreadPool.QueueUserWorkItem(p => myExpensiveMethod()); } private static void myExpensiveMethod() { //Some expensive stuff here... //Read from Database/Internet //Perform some calculations if (salaryTextBox.InvokeRequired) salaryTextBox.Invoke(new Action(() => salaryTextBox.Text = result)); }
  6. 6. private int myExpensiveMethod() { ... return 42; } private void Button1_Click(object sender, EventArgs e) { var function = new Func<int>(myExpensiveMethod); IAsyncResult result = function.BeginInvoke(whenFinished, function); } private void whenFinished(IAsyncResult ar) { var function = ar.AsyncState as Func<int>; int result = function.EndInvoke(ar); resultTextBox.Text = string.Format("The answer is... {0}!", result); }
  7. 7. var numbers = Enumerable.Range(1, 10000000); var query = numbers.AsParallel().Where(n => n.IsPrime()); var primes = query.ToArray(); 1 2 3 4 5 6 7 8 OS Cores1 2 3 4 5 6 7 8 7 3 2 5 2 3 5 7
  8. 8. var customers = Customer.GetSampleCustomers(); Parallel.ForEach(customers, c => { if(!c.IsActive) c.Balance = 0; });
  9. 9. public static List<string> GetNetworkSQLServerInstances() { //Get local network servers return servers; } private void updateServersList(List<string> severs) { listBox1.Items.AddRange(servers.ToArray()); } //SYNC version private void Button1_Click(object sender, EventArgs e) { var servers = GetNetworkSQLServerInstances(); updateServersList(servers); }
  10. 10. public static List<string> GetNetworkSQLServerInstances() { //Get local network servers return servers; } private void updateServersList(List<string> severs) { listBox1.Items.AddRange(servers.ToArray()); } //ASYNC version private void Button1_Click(object sender, EventArgs e) { var serversTask = Task.Factory.StartNew(() => GetNetworkSQLServerInstances()); serversTask.ContinueWith(t => updateServersList(serversTask.Result)); }
  11. 11. public static List<string> GetNetworkSQLServerInstances() { //Get local network servers return servers; } private void updateServersList(List<string> severs) { listBox1.Items.AddRange(servers.ToArray()); } //ASYNC version + context synchronization private void Button1_Click(object sender, EventArgs e) { var serversTask = Task.Factory.StartNew(() => GetNetworkSQLServerInstances()); serversTask.ContinueWith(t => updateServersList(serversTask.Result), TaskScheduler.FromCurrentSynchronizationContext()); }
  12. 12. public static List<string> GetNetworkSQLServerInstances() { //Get local network servers return servers; } private void updateServersList(List<string> severs) { listBox1.Items.AddRange(servers.ToArray()); } //ASYNC/AWAIT version private async void Button1_Click(object sender, EventArgs e) { var servers = await Task.Run(() => GetNetworkSQLServerInstances()); updateServersList(servers); }
  13. 13. public static Task<List<string>> GetNetworkSQLServerInstancesAsync() { //Get local network servers return servers; } //ASYNC/AWAIT version 1 private async void Button1_Click(object sender, EventArgs e) { var servers = await Task.Run(() => GetNetworkSQLServerInstances()); updateServersList(servers); } //ASYNC/AWAIT version 2 (REAL async) private async void Button1_Click(object sender, EventArgs e) { var servers = await GetNetworkSQLServerInstancesAsync(); updateServersList(servers); }
  14. 14.     //ASYNC/AWAIT version private async void Button1_Click(object sender, EventArgs e) { var servers = await GetNetworkSQLServerInstancesAsync(); updateServersList(servers); }
  15. 15. public static void SimpleBody() { Console.WriteLine("Hello, Async World!"); } .method public hidebysig static void SimpleBody() cil managed { .maxstack 8 L_0000: ldstr "Hello, Async World!" L_0005: call void [mscorlib]System.Console::WriteLine(string) L_000a: ret }
  16. 16. public static async Task SimpleBody() { Console.WriteLine("Hello, Async World!"); } .method public hidebysig static class [mscorlib]System.Threading.Tasks.Task SimpleBody() cil managed { .custom instance void [mscorlib]System.Diagnostics.DebuggerStepThroughAttribute::.ctor() = ( 01 00 00 00 ) // Code size 32 (0x20) .maxstack 2 .locals init ([0] valuetype Program/'<SimpleBody>d__0' V_0) IL_0000: ldloca.s V_0 IL_0002: call valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder::Create() IL_0007: stfld valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program/'<SimpleBody>d__0'::'<>t__builder' IL_000c: ldloca.s V_0 IL_000e: call instance void Program/'<SimpleBody>d__0'::MoveNext() IL_0013: ldloca.s V_0 IL_0015: ldflda valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program/'<SimpleBody>d__0'::'<>t__builder' IL_001a: call instance class [mscorlib]System.Threading.Tasks.Task [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder::get_Task() IL_001f: ret } .method public hidebysig instance void MoveNext() cil managed { // Code size 66 (0x42) .maxstack 2 .locals init ([0] bool '<>t__doFinallyBodies', [1] class [mscorlib]System.Exception '<>t__ex') .try { IL_0000: ldc.i4.1 IL_0001: stloc.0 IL_0002: ldarg.0 IL_0003: ldfld int32 Program/'<SimpleBody>d__0'::'<>1__state' IL_0008: ldc.i4.m1 IL_0009: bne.un.s IL_000d IL_000b: leave.s IL_0041 IL_000d: ldstr "Hello, Async World!" IL_0012: call void [mscorlib]System.Console::WriteLine(string) IL_0017: leave.s IL_002f } catch [mscorlib]System.Exception { IL_0019: stloc.1 IL_001a: ldarg.0 IL_001b: ldc.i4.m1 IL_001c: stfld int32 Program/'<SimpleBody>d__0'::'<>1__state' IL_0021: ldarg.0 IL_0022: ldflda valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program/'<SimpleBody>d__0'::'<>t__builder' IL_0027: ldloc.1 IL_0028: call instance void [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder::SetException( class [mscorlib]System.Exception) IL_002d: leave.s IL_0041 } IL_002f: ldarg.0 IL_0030: ldc.i4.m1 IL_0031: stfld int32 Program/'<SimpleBody>d__0'::'<>1__state' IL_0036: ldarg.0 IL_0037: ldflda valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program/'<SimpleBody>d__0'::'<>t__builder' IL_003c: call instance void [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder::SetResult() IL_0041: ret }
  17. 17. private async void Button1_Click(object Sender, EventArgs e) { try { SendData("https://secure.flickr.com/services/oauth/request_token"); await Task.Delay(2000); DebugPrint("Received Data: " + m_GetResponse); } catch (Exception ex) { rootPage.NotifyUser("Error posting data to server." + ex.Message); } } private async void SendData(string Url) { var request = WebRequest.Create(Url); using (var response = await request.GetResponseAsync()) using (var stream = new StreamReader(response.GetResponseStream())) m_GetResponse = stream.ReadToEnd(); }
  18. 18. private async void Button1_Click(object Sender, EventArgs e) { try { SendData("https://secure.flickr.com/services/oauth/request_token"); // await Task.Delay(2000); // DebugPrint("Received Data: " + m_GetResponse); } catch (Exception ex) { rootPage.NotifyUser("Error posting data to server." + ex.Message); } } private async void SendData(string Url) { var request = WebRequest.Create(Url); using (var response = await request.GetResponseAsync()) // exception on resumption using (var stream = new StreamReader(response.GetResponseStream())) m_GetResponse = stream.ReadToEnd(); }
  19. 19. private async void Button1_Click(object Sender, EventArgs e) { try { SendData("https://secure.flickr.com/services/oauth/request_token"); await Task.Delay(2000); DebugPrint("Received Data: " + m_GetResponse); } catch (Exception ex) { rootPage.NotifyUser("Error posting data to server." + ex.Message); } } private async void SendData(string Url) { var request = WebRequest.Create(Url); using (var response = await request.GetResponseAsync()) using (var stream = new StreamReader(response.GetResponseStream())) m_GetResponse = stream.ReadToEnd(); } Task Async Async await
  20. 20. // Q. It sometimes shows PixelWidth and PixelHeight are both 0 ??? BitmapImage m_bmp; protected override async void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); await PlayIntroSoundAsync(); image1.Source = m_bmp; Canvas.SetLeft(image1, Window.Current.Bounds.Width - m_bmp.PixelWidth); } protected override async void LoadState(Object nav, Dictionary<String, Object> pageState) { m_bmp = new BitmapImage(); var file = await StorageFile.GetFileFromApplicationUriAsync("ms-appx:///pic.png"); using (var stream = await file.OpenReadAsync()) { await m_bmp.SetSourceAsync(stream); } } class LayoutAwarePage : Page { private string _pageKey; protected override void OnNavigatedTo(NavigationEventArgs e) { if (this._pageKey != null) return; this._pageKey = "Page-" + this.Frame.BackStackDepth; ... this.LoadState(e.Parameter, null); } }
  21. 21. // A. Use a task Task<BitmapImage> m_bmpTask; protected override async void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); await PlayIntroSoundAsync(); var bmp = await m_bmpTask; image1.Source = bmp; Canvas.SetLeft(image1, Window.Current.Bounds.Width - bmp.PixelWidth); } protected override void LoadState(Object nav, Dictionary<String, Object> pageState) { m_bmpTask = LoadBitmapAsync(); } private async Task<BitmapImage> LoadBitmapAsync() { var bmp = new BitmapImage(); ... return bmp; }
  22. 22. ' In VB, the expression itself determines void- or Task-returning (not the context). Dim void_returning = Async Sub() Await LoadAsync() : m_Result = "done" End Sub Dim task_returning = Async Function() Await LoadAsync() : m_Result = "done" End Function ' If both overloads are offered, you must give it Task-returning. Await Task.Run(Async Function() ... End Function) // In C#, the context determines whether async lambda is void- or Task-returning. Action a1 = async () => { await LoadAsync(); m_Result="done"; }; Func<Task> a2 = async () => { await LoadAsync(); m_Result="done"; }; // Q. Which one will it pick? await Task.Run( async () => { await LoadAsync(); m_Result="done"; }); // A. If both overloads are offered, it will pick Task-returning. Good! class Task { static public Task Run(Action a) {...} static public Task Run(Func<Task> a) {...} ... }
  23. 23. // table1.DataSource = LoadHousesSequentially(1,5); // table1.DataBind(); public List<House> LoadHousesSequentially(int first, int last) { var loadedHouses = new List<House>(); for (int i = first; i <= last; i++) { House house = House.Deserialize(i); loadedHouses.Add(house); } return loadedHouses; } work1 work2 work3 work4 work5
  24. 24. // table1.DataSource = LoadHousesInParallel(1,5); // table1.DataBind(); public List<House> LoadHousesInParallel(int first, int last) { var loadedHouses = new BlockingCollection<House>(); Parallel.For(first, last+1, i => { House house = House.Deserialize(i); loadedHouses.Add(house); }); return loadedHouses.ToList(); } 3 response out 300ms work1 work2 work3 work4 work5 Parallel.For Parallelization hurts Scalability!
  25. 25. end1 start1 end2 start2 end3 start3 end4 start4 end5 start5
  26. 26. 3end3 start3 end1 start1 end2 start2 end5 start5 response out ~200ms Parallel.For end3 start3 end4 start4
  27. 27. end2 start1 start2 start3 start4 start5 response out ~100ms end5 end1 end3 end4
  28. 28. // table1.DataSource = await LoadHousesAsync(1,5); // table1.DataBind(); public async Task<List<House>> LoadHousesAsync(int first, int last) { var tasks = new List<Task<House>>(); for (int i = first; i <= last; i++) { Task<House> t = House.LoadFromDatabaseAsync(i); tasks.Add(t); } House[] loadedHouses = await Task.WhenAll(tasks); return loadedHouses.ToList(); } When… methods minimize awaits + exceptions
  29. 29. public async void btnPayout_Click(object sender, RoutedEventArgs e) { double initialPrice, strikePrice, drift, volatility = from UI double[] prices = new double[252]; double total_payout = 0; for (int i = 0; i < 1000000; i++) { Quant.SimulateStockPrice(prices, initialPrice, drift, volatility); total_payout += Quant.Payout_AsianCallOption(prices, strikePrice); } txtExpectedPayout.Text = (total_payout / 1000000).ToString(); } //Box-Muller technique, generates "standard normal" distribution (mean=0, variance=1) let private NextNormal () = let u1 = RND.NextDouble() let u2 = RND.NextDouble() sqrt(-2.0 * log u1) * sin(2.0 * System.Math.PI * u2) //Geometric Brownian Monion, a common technique to model stock price let SimulateStockPrice (prices:double[], initialPrice, drift, volatility) = let dt = 1.0 float prices.Length let red sim i value = prices.[i] <- value let nextval = value * (1.0 + drift*dt + volatility*NextNormal()*sqrt dt) if i+1 < prices.Length then sim (i+1) (if nextval < 0.0 then 0.0 else nextval) sim 0 inicialprice //An Asian Call Option gives payout if strike price is lower than the average stock price let Payout_Asiancalloption (prices, strikePrice) = let av = Array.average prices max (av - strikePrice) 0.0
  30. 30. public async void btnPayout_Click(object sender, RoutedEventArgs e) { double initialPrice, strikePrice, drift, volatility = from UI var expectedPayout = await Task.Run(() => { double[] prices = new double[252]; double total_payout = 0; for (int i = 0; i < 1000000; i++) { Quant.SimulateStockPrice(prices, initialPrice, drift, volatility); total_payout += Quant.Payout_AsianCallOption(prices, strikePrice); } return total_payout / 1000000; }); txtExpectedPayout.Text = expectedPayout.ToString(); }
  31. 31. public async void btnPayout_Click(object sender, RoutedEventArgs e) { double initialPrice, strikePrice, drift, volatility = from UI IProgress<int> progress = new Progress<int>(i => progressBar1.Value = i); var expectedPayout = await Task.Run(() => { double[] prices = new double[252]; double total_payout = 0; for (int i = 0; i < 1000000; i++) { Quant.SimulateStockPrice(prices, initialPrice, drift, volatility); total_payout += Quant.Payout_AsianCallOption(prices, strikePrice); if(i % 1000 == 0) progress.Report(i); } return total_payout / 1000000; }); txtExpectedPayout.Text = expectedPayout.ToString(); }
  32. 32. Foo(); var task = FooAsync(); ... await task; synchronous perform when it’s done asynchronous initiate immediately
  33. 33. public static void PausePrint2() { Task t = PausePrintAsync(); t.Wait(); } // “I’m not allowed an async signature, // but my underlying library is async” public static Task PausePrint2Async() { return Task.Run(() => PausePrint()); } // “I want to offer an async signature, // but my underlying library is synchronous” public static Task PausePrintAsync() { var tcs = new TaskCompletionSource<bool>(); new Timer(_ => { Console.WriteLine("Hello"); tcs.SetResult(true); }).Change(10000, Timeout.Infinite); return tcs.Task; } public static async Task PausePrintAsync() { await Task.Delay(10000); Console.WriteLine("Hello"); } Synchronous Asynchronous public static void PausePrint() { var end = DateTime.Now + TimeSpan.FromSeconds(10); while (DateTime.Now < end) { } Console.WriteLine("Hello"); } “Should I expose async wrappers for synchronous methods?” – generally no! http://blogs.msdn.com/b/pfxteam/archive/2012/03/24/10287244.aspx “How can I expose sync wrappers for async methods?” – if you absolutely have to, you can use a nested message-loop… http://blogs.msdn.com/b/pfxteam/archive/2012/04/13/10293638.aspx
  34. 34. The threadpool is an app-global resource In a server app, spinning up threads hurts scalability The app is in the best position to manage its threads synchronous blocks the current thread asynchronous without spawning new threads
  35. 35. async Task LoadAsync() { await IO.Network.DownloadAsync(path); } void Button1_Click(){ var t = LoadAsync(); t.Wait(); UpdateView(); } Click Messagepump Task ... DownloadAsync Task ... LoadAsync Download
  36. 36. server scalability.
  37. 37. We all know sync methods are “cheap” public static void SimpleBody() { Console.WriteLine("Hello, Async World!"); } .method public hidebysig static void SimpleBody() cil managed { .maxstack 8 L_0000: ldstr "Hello, Async World!" L_0005: call void [mscorlib]System.Console::WriteLine(string) L_000a: ret }
  38. 38. Not so for asynchronous methods public static async Task SimpleBody() { Console.WriteLine("Hello, Async World!"); } .method public hidebysig static class [mscorlib]System.Threading.Tasks.Task SimpleBody() cil managed { .custom instance void [mscorlib]System.Diagnostics.DebuggerStepThroughAttribute::.ctor() = ( 01 00 00 00 ) // Code size 32 (0x20) .maxstack 2 .locals init ([0] valuetype Program/'<SimpleBody>d__0' V_0) IL_0000: ldloca.s V_0 IL_0002: call valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder::Create() IL_0007: stfld valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program/'<SimpleBody>d__0'::'<>t__builder' IL_000c: ldloca.s V_0 IL_000e: call instance void Program/'<SimpleBody>d__0'::MoveNext() IL_0013: ldloca.s V_0 IL_0015: ldflda valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program/'<SimpleBody>d__0'::'<>t__builder' IL_001a: call instance class [mscorlib]System.Threading.Tasks.Task [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder::get_Task() IL_001f: ret } .method public hidebysig instance void MoveNext() cil managed { // Code size 66 (0x42) .maxstack 2 .locals init ([0] bool '<>t__doFinallyBodies', [1] class [mscorlib]System.Exception '<>t__ex') .try { IL_0000: ldc.i4.1 IL_0001: stloc.0 IL_0002: ldarg.0 IL_0003: ldfld int32 Program/'<SimpleBody>d__0'::'<>1__state' IL_0008: ldc.i4.m1 IL_0009: bne.un.s IL_000d IL_000b: leave.s IL_0041 IL_000d: ldstr "Hello, Async World!" IL_0012: call void [mscorlib]System.Console::WriteLine(string) IL_0017: leave.s IL_002f } catch [mscorlib]System.Exception { IL_0019: stloc.1 IL_001a: ldarg.0 IL_001b: ldc.i4.m1 IL_001c: stfld int32 Program/'<SimpleBody>d__0'::'<>1__state' IL_0021: ldarg.0 IL_0022: ldflda valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program/'<SimpleBody>d__0'::'<>t__builder' IL_0027: ldloc.1 IL_0028: call instance void [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder::SetException( class [mscorlib]System.Exception) IL_002d: leave.s IL_0041 } IL_002f: ldarg.0 IL_0030: ldc.i4.m1 IL_0031: stfld int32 Program/'<SimpleBody>d__0'::'<>1__state' IL_0036: ldarg.0 IL_0037: ldflda valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program/'<SimpleBody>d__0'::'<>t__builder' IL_003c: call instance void [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder::SetResult() IL_0041: ret }
  39. 39. public static async Task<int> GetNextIntAsync() { if (m_Count == m_Buf.Length) { m_Buf = await FetchNextBufferAsync(); m_Count = 0; } m_Count += 1; return m_Buf[m_Count - 1]; }
  40. 40. var x = await GetNextIntAsync(); var $awaiter = GetNextIntAsync().GetAwaiter(); if (!$awaiter.IsCompleted) { DO THE AWAIT/RETURN AND RESUME; } var x = $awaiter.GetResult();
  41. 41. public static async Task<int> GetNextIntAsync() { if (m_Count == m_Buf.Length) { m_Buf = await FetchNextBufferAsync(); m_Count = 0; } m_Count += 1; return m_Buf[m_Count - 1]; }
  42. 42. The heap is an app-global resource. Like all heap allocations, async allocations can contributing to hurting GC perf.
  43. 43. Sync context represents a “target for work” “Await task” uses the sync context “where you were before” But for library code, it’s rarely needed! You can use “await task.ConfigureAwait(false)” This suppresses step 2; instead if possible it resumes “on the thread that completed the task” Result: slightly better performance. Also can avoid deadlock if a badly-written user blocks.
  44. 44. UI responsiveness
  45. 45. Lluis Franco & Alex Casquete Async best practices ¡¡¡Si te ha gustado no olvides rellenar la encuesta!!! Thanks Y A X B

×