1 Krótka historia asynchroniczności w.NET 1-4.5 Jakub Binkowski
2 O mnie Jakub Binkowski Senior.NET Developer @ Rule Financial Microsoft MVP w latach 2008-2011 MCP, MCTS, MCPD Lider Łódzkiej Grupy Profesjonalistów IT &.NET [email protected]
3 Agenda Dlaczego asynchroniczność? Jak? Asynchronous Programming Model (APM) Event-based Asynchronous Pattern (EAP) Task-based Asynchronous Pattern (TAP) Async i await w.NET 4.5 Asynchroniczny ASP.NET Testy jednostkowe
4 Dlaczego asynchroniczność?
5 Przypomnienie: Wątek jest drogi Pamięć: ponad 1MB (pamięć zarezerwowana) Czas: Powiadomienia o utworzeniu i zamknięciu wątku (do wszystkich DLL) Przełączenia kontekstu
6 Przypomnienie: Pula wątków Zbiór wątków dostępnych dla aplikacji Jedna na proces (CLR) Ilość wątków w puli Minimalna ilość wątków = ilość procesorów logicznych Maksymalna – zależy od środowiska Algorytm – czarna skrzynka Klasa ThreadPool
7 Przykład 1 – ASP.NET
8 public ActionResult AvatarDetails() { var url = "http://..."; var data = new WebClient().DownloadData(url); var bitmap = new Bitmap(new MemoryStream(data)); var model = new AvatarModel { AvatarUrl = url, Size = data.Length, Width = bitmap.Width, Height = bitmap.Height }; return View(model); }
9 Gdzie jest problem? Pula wątków obsługujących żądania Dla uproszczenia – pula = 3 wątki; 3 procesory HTML DB Web Service HTML CPU = 66% Web Service
10 Gdzie jest problem? Pula wątków obsługujących żądania Dla uproszczenia – pula = 3 wątki; 3 procesory HTML DB Web Service CPU = 33% Web Service HTML
11 Gdzie jest problem? Pula wątków obsługujących żądania Dla uproszczenia – pula = 3 wątki; 3 procesory HTML DB Web Service CPU = 0% Web Service HTML !
12 Operacje obliczeniowe Wątek
13 Operacje I/O (synchroniczne) Operacja I/O Wątek Urządzenie
14 Gdyby… 1 cykl procesora = 1 sekunda: Rejestr: 1s Pamięć: 5-10s Dysk: 3 miesiące Sieć: 30 lat
15 Przykład 2 - WPF
16 void Button_Click(object sender, RoutedEventArgs e) { var data = new WebClient().DownloadData(tbUrl.Text); var bitmap = new BitmapImage(); bitmap.BeginInit(); bitmap.StreamSource = new MemoryStream(data); bitmap.EndInit(); imgAvatar.Source = bitmap; } Uwaga! Brzydki kod Uwaga! Brzydki kod
17 Przykład 2 – WPF (aplikacja desktop) Tylko jeden wątek obsługuje UI W czasie wykonywania operacji aplikacja nie odpowiada
18 Programowanie synchroniczne Problemy Problem 1: Pula wątków blokowana przez zewnętrzne urządzenia (I/O) Problem 2: Wątek UI zajęty przez długotrwałą operację
19 Wzorce asynchroniczne APM vs EAP vs TAP
20 Kod synchroniczny API: public interface IMyType { int DoSomething(int a); } Wywołanie: IMyType type = /*..*/; int result = type.DoSomething(10);
21 Asynchronous Programming Model API public interface IMyType { IAsyncResult BeginDoSomething(int a, AsyncCallback callback, object state); int EndDoSomething(IAsyncResult asyncResult); }
22 Asynchronous Programming Model Użycie – wariant 1 IMyType type = /*..*/; IAsyncResult asyncRes = type.BeginDoSomething(10, null, null); //... int result = type.EndDoSomething(asyncRes); //...
23 Asynchronous Programming Model Użycie – wariant 2 class MyProgram { private IMyType _type; public void Begin() { _type.BeginDoSomething(10, OnDoSomethingFinished, null); } private void OnDoSomethingFinished(IAsyncResult asyncRes) { int result = _type.EndDoSomething(asyncRes); //... }
24 Asynchronous Programming Model Użycie – wariant 2b IMyType type = /*..*/; type.BeginDoSomething(10, asyncRes => { int result = type.EndDoSomething(asyncRes); //... }, null);
25 Demo Asynchronous Programming Model
26 Trochę historii Oryginalnie IAsyncResult jedynym wzorcem Wg zespołu Windows Forms IAsyncResult jest zbyt skomplikowany nie pasuje do trybu design wymaga pilnowania wątków Efekt – alternatywne podejście: Event-base Asynchronous Programming
27 Event-based Asynchronous Programming API public interface IMyType { void DoSomethingAsync(int a); event DoSomethingCompletedEventHandler DoSomethingCompleted; } public class DoSomethingCompletedEventArgs: AsyncCompletedEventArgs { public int Result { get; set; } /*…*/ } public delegate void DoSomethingCompletedEventHandler( object sender, DoSomethingCompletedEventArgs args);
28 Event-based Asynchronous Programming Użycie IMyType type = /*...*/; type.DoSomethingCompleted += (sender, args) => { int result = args.Result; //... }; type.DoSomethingAsync(10);
29 Demo Event-based Asynchronous Programming
30 APM Zastosowanie FCL: 60 klas Strumienie ( System.IO.Stream ) DNS ( System.Net.Dns ) Gniazda sieciowe ( System.Net.Sockets.Socket ) Żądania sieciowe ( System.Net.WebRequest ) Polecenia SQL ( System.Data.SqlClient.SqlCommand ) Porty ( System.IO.Ports.SerialPort ) Web/Service References
31 EAP Zastosowanie FCL: 17 klas System.ComponentModel.BackgroundWorker; System.Net.WebClient; System.Net.NetworkInformation.Ping; System.Windows.Forms.PictureBox; System.Net.Mail.SmtpClient; i inne…
32 APM czy EAP?
33 Gdzie jest problem?
34 Gdzie jest problem?
35 W drodze ku lepszemu.NET 4.0 wprowadził nowy model programowania równoległego – Task Parallel Library C# 4.5 wprowadzi nowy model programowania asynchronicznego: Task-based Asynchronous Programming APM i EAP staną się przestarzałe
36 Idea TAP Niech deweloperzy piszą kod prawie tak samo Magią niech zajmie się kompilator
37 Task-based Asynchronous Programming API public interface IMyType { Task DoSomethingTask(int a); }
38 Task-based Asynchronous Programming API public interface IMyType { Task DoSomethingTask(int a); }
39 Task-based Asynchronous Programming Użycie public async Task IsSomethingZeroAsync(int a) { IMyType type = /*...*/; var value = await type.DoSomethingAsync(a); return value == 0; }
40 Task-based Asynchronous Programming Użycie public async Task IsSomethingZeroAsync(int a) { IMyType type = /*...*/; var value = await type.DoSomethingAsync(a); return value == 0; }
41 Task-based Asynchronous Programming Użycie public async Task IsSomethingZeroAsync(int a) { IMyType type = /*...*/; var value = await type.DoSomethingAsync(a); return value == 0; }
42 Task-based Asynchronous Programming Użycie public async Task IsSomethingZeroAsync(int a) { IMyType type = /*...*/; var value = await type.DoSomethingAsync(a); return value == 0; }
43 Demo Task-based Asynchronous Programming
44 ASP.NET Asynchroniczne ASP.NET MVC 3 i 4
45 Demo ASP.NET MVC 3
46 Synchroniczny kontroler ASP.NET MVC 3 public class HomeController : Controller { public ActionResult AvatarDetails() { var client = new WebClient(); var data = client.DownloadData(new Uri("…")); //... return View(); } }
47 Asynchroniczny kontroler ASP.NET MVC 3 public class HomeController : AsyncController { public void AvatarDetailsAsync() { 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(); } }
48 Asynchroniczny kontroler ASP.NET MVC 3 public class HomeController : AsyncController { public void AvatarDetailsAsync() { 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(); } }
49 Asynchroniczny kontroler ASP.NET MVC 3 public class HomeController : AsyncController { public void AvatarDetailsAsync() { 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(); } }
50 Asynchroniczny kontroler ASP.NET MVC 3 public class HomeController : AsyncController { public void AvatarDetailsAsync() { 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(); } }
51 Demo ASP.NET MVC 4 + async
52 Synchroniczny kontroler ASP.NET MVC 4 public class HomeController : Controller { public ActionResult AvatarDetails() { var client = new WebClient(); var data = client.DownloadData(new Uri("…")); //... return View(); } }
53 Asynchroniczny kontroler ASP.NET MVC 4 public class HomeController : AsyncController { public async Task AvatarDetails() { var client = new WebClient(); var data = await client.DownloadDataTaskAsync(new Uri("…")); //... return View(); } }
54 Asynchroniczny kontroler ASP.NET MVC 4 public class HomeController : AsyncController { public async Task AvatarDetails() { var client = new WebClient(); var data = await client.DownloadDataTaskAsync(new Uri("…")); //... return View(); } }
55 Asynchroniczny kontroler ASP.NET MVC 4 public class HomeController : AsyncController { public async Task AvatarDetails() { var client = new WebClient(); var data = await client.DownloadDataTaskAsync(new Uri("…")); //... return View(); } }
56 async a testy jednostkowe
57 Demo Synchronous unit tests
58 Demo Asynchronous unit tests
59 Podsumowanie 3 wzorce programowania asynchronicznego: APM (Asynchronous Programming Model) EAP (Event-based Asynchronous Programming) TAP (Task-based Asynchronous Programming) TAP zastępuje APM i EAP nowe metody w całym.NET Framework wsparcie w ASP.NET wsparcie w WCF Potężne wsparcie kompilatora – async i await
60 Przydatne odnośniki http://www.albahari.com/threading/ Asynchronous programming design patterns: http://msdn.microsoft.com/en-us/library/ms228969.aspx http://msdn.microsoft.com/en-us/library/ms228969.aspx Asynchronous ASP.NET: http://msdn.microsoft.com/en-us/magazine/cc163725.aspx http://msdn.microsoft.com/en-us/library/ee728598.aspx Asynchronous WCF: http://msdn.microsoft.com/en-us/library/ms734701.aspx http://msdn.microsoft.com/en-us/library/ms734701.aspx
61 Przydatne odnośniki – async TAP in-depth: http://www.microsoft.com/download/en/details.aspx?id=1 9957 http://www.microsoft.com/download/en/details.aspx?id=1 9957 Visual Studio 11 CTP: http://www.microsoft.com/download/en/details.aspx?displ aylang=en&id=27543 http://www.microsoft.com/download/en/details.aspx?displ aylang=en&id=27543 ASP.NET MVC 4 CTP: http://www.microsoft.com/web/gallery/install.aspx?appid= MVC4VS11&prerelease=true http://www.microsoft.com/web/gallery/install.aspx?appid= MVC4VS11&prerelease=true Jon Skeet blog: http://msmvps.com/blogs/jon_skeet/http://msmvps.com/blogs/jon_skeet/
62 Dziękuję za uwagę. Pytania?