Asynchroniczność w Windows 8 Jakub Binkowski
O mnie Jakub Binkowski Lead.NET Developer
Agenda Dlaczego asynchronicz- ność? Historia: APM, EAPasync i await ASP.NET MVC Windows 8 Runtime Internals i architektura
Dlaczego asynchroniczność?
public void DownloadImageAsPng(string url, string fileName) { var webclient = new WebClient(); var imageBytes = webclient.DownloadData(url); using(var imageStream = new MemoryStream(imageBytes)) { var bitmap = Bitmap.FromStream(imageStream); bitmap.Save(fileName, ImageFormat.Png); } Przykładowa metoda… Pobranie z sieci Zapis na dysk
Gdyby 1 cykl procesora = 1 sekunda: Rejestr: 1s Pamięć: 5-10s Dysk: 3 miesiące Sieć: 30 lat Ile to trwa?
Operacje obliczeniowe Wątek
Operacje I/O synchroniczne Operacja I/O Wątek Urządzenie
Różne problemy w różnych środowiskach: Aplikacje desktop (Metro, WPF, …) Aplikacje serwerowe (ASP.NET, WCF, …) Problemy
Jest jeden wątek UI Gdy jest zajęty aplikacja przestaje odpowiadać Aplikacje desktop
Oparte o pulę wątków Gdy wszystkie wątki z puli są zajęte – żądania się kolejkują Pula wątków rośnie, ale: Każdy wątek to 1MB zarezerwowanej pamięci Aplikacje serwerowe
Dla uproszczenia: 3 procesory 3 wątki w puli 2 rodzaje operacji: Tylko HTML – szybka operacja w pamięci Dostęp do zewnętrznych zasobów (DB, Web Service) - wole Przykład – aplikacja ASP.NET
HTML DB Web Service HTML CPU = 66% DB Żądania aktualnie obsługiwane Żądania aktualnie obsługiwane Kolejka żądań oczekujących Kolejka żądań oczekujących HTML
Przykład – aplikacja ASP.NET HTML DB Web Service HTML CPU = 33% DB HTML
Przykład – aplikacja ASP.NET HTML DB Web Service CPU = 0% DB HTML Żądania, które można by obsłużyć… Żądania, które można by obsłużyć…
Desktop zawieszenie się Server spadek wydajności Rozwiązanie – operacje asynchroniczne Problemy operacji synchronicznych
Operacje I/O asynchroniczne Operacja I/O Wątek 1 Urządzenie Wątek 2
Krótka historia asynchroniczności w.NET
Asynchronous Programming Model Asynchroniczność w.NET 1.1 Demo
Wg zespołu Windows Forms APM jest: zbyt skomplikowany nie pasuje do trybu design wymaga pilnowania wątków Asynchronous Programming Model
Event-base Asynchronous Programming Asynchroniczność w.NET 2.0 Demo
public void DownloadFile(string url) { try { var webClient = new WebClient(); var data = webClient.DownloadData(url); //carry on... } catch (Exception ex) { //handle error... } Problem APM i EAP…
public void DownloadFile(string url) { try { var webClient = new WebClient(); webClient.DownloadDataCompleted += DownloadFileCompleted; webClient.DownloadDataAsync(new Uri(url)); } catch (Exception ex) { //handle error } private void DownloadFileCompleted(object sender, DownloadDataCompletedEventArgs e) { if (e.Error == null) { var data = e.Result; //carry on... } else { //handle error } Problem APM i EAP…
Napisać taki kod jak synchroniczny Niech kompilator zajmie się asynchronicznością Niech debugger działa jak gdyby kod był synchroniczny A gdyby można było…
A gdyby tak można było…
public async void DownloadFile(string url) { try { var webClient = new WebClient(); var data = await webClient.DownloadDataTaskAsync( new Uri(url)); //carry on... } catch (Exception ex) { //handle error... } async!
public async Task DownloadFile(string url) { var wc = new WebClient(); var data = await wc.DownloadDataTaskAsync(/*...*/); //carry on... } Jak działa async?
async Demo
public Task DownloadFile(string url) { var wc = new WebClient(); var downloadTask = wc.DownloadDataTaskAsync(/*...*/); var continuationTask = downloadTask.ContinueWith(t => { if (t.Exception != null) throw t.Exception.InnerException; //carry on... }); return continuationTask; } Co zrobi kompilator?
public async void FireAndForget() { /*...*/ } public async Task FireAndRemember() { /*...*/ } public async Task FireAndReturn() { /*...*/ return 1; } Metody async
Fire and forget Przeznaczenie: Event handlery Kompatybilność wstecz async Task vs async void Można poczekać na zakończenie wykonania (i sprawdzić np. exception) async void Xxx()async Task Xxx()
Func > fireAndReturn = async ()=> { /**/ return 1; }; Anonimowy async? Czemu nie!
ASP.NET MVC async
public class HomeController : Controller { public ActionResult Download() { var client = new WebClient(); var data = client.DownloadData(new Uri("…")); //... return View(); } } ASP.NET MVC 3 – kontroler Potencjalnie długotrwała operacja
public class HomeController : AsyncController { public void DownloadAsync() { AsyncManager.OutstandingOperations.Increment(); var client = new WebClient(); client.DownloadDataCompleted += (s, a) => { AsyncManager.Parameters["data"] = a.Result; AsyncManager.OutstandingOperations.Decrement(); }; client.DownloadDataAsync(new Uri("…")); } public ActionResult AvatarDetailsCompleted(byte[] data) { //... return View(); } } ASP.NET MVC 3 – kontroler asynchroniczny
ASP.NET MVC 3 Kontroler synchroniczny Kontroler asynchroniczn y Demo
public class HomeController : Controller { public ActionResult Download() { var client = new WebClient(); var data = client.DownloadData(new Uri("…")); //... return View(); } } ASP.NET MVC 4 – kontroler synchroniczny (przypomnienie)
public class HomeController : AsyncController { public async Task Download() { var client = new WebClient(); var data = await client.DownloadDataTaskAsync(/*…*/); //... return View(); } } ASP.NET MVC 4 – kontroler asynchroniczny
ASP.NET MVC 4 Kontroler asynchroniczn y Demo
Windows Runtime async
Async w Windows Runtime Fundamentals Communications & Data Media Devices User Interface
Asynchroniczność w Windows Runtime Demo
Async w Windows Runtime
IAsync* a Task IAsyncAction IAsyncOperation Task
Internals, architektura
Na jakim wątku wykona się dalej kod? Demo
Czy skoro można wywołać na: Task IAsyncAction/Operation to czy można wywołać na czymś jeszcze innym? Pytanie
await – na czym można czekać? public class MyClass { public MyAwaiter GetAwaiter() { /*..*/ } } public class MyAwaiter : INotifyCompletion { public bool IsCompleted { get {/*...*/} } public void GetResult() {/*..*/} public void OnCompleted(Action continuation) {/*..*/} } var my = new MyClass(); await my; Może też być extension method Może też być extension method
Co będzie w zmiennej type? var task = Task.Run ( new Func (() => { throw new Exception(); })); try { await task; } catch (Exception ex) { string type = ex.GetType().Name; } var task = Task.Run ( new Func (() => { throw new Exception(); })); try { await task; } catch (Exception ex) { string type = ex.GetType().Name; } var task = Task.Run ( new Func (() => { throw new Exception(); })); task.ContinueWith(t => { try { var res = t.Result; } catch (Exception ex) { string type = ex.GetType().Name; } }); var task = Task.Run ( new Func (() => { throw new Exception(); })); task.ContinueWith(t => { try { var res = t.Result; } catch (Exception ex) { string type = ex.GetType().Name; } });
await a Exception Demo
private async void Button_Click_1(object sender, RoutedEventArgs e) { var wc = new WebClient(); var data = await wc.DownloadDataTaskAsync(tb.Text); //... } Czy tak piszemy aplikacje?
Wzorce, np. MVVM? Warstwy: logiki biznesowej, dostępu do danych? Co z tą architekturą?
Wpływ async na architekturę Demo
async – okiełznanie asynchroniczności W.NET – nowe metody W Windows Runtime – jedyny model Pełne wsparcie w ASP.NET, WCF Wpływ na architekturę Podsumowanie
Dziękuję za uwagę! Pytania?