Krótka historia asynchroniczności w .NET 1-4.5

Post on 10-Feb-2016

44 views 0 download

description

Krótka historia asynchroniczności w .NET 1-4.5. Jakub Binkowski. 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 Jakub@Binkowski.com.pl. Agenda. Dlaczego asynchroniczność? - PowerPoint PPT Presentation

Transcript of Krótka historia asynchroniczności w .NET 1-4.5

Krótka historiaasynchroniczności w .NET 1-4.5

Jakub Binkowski

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

Jakub@Binkowski.com.pl

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

Dlaczego asynchroniczność?

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

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

Przykład 1 – ASP.NET

Przykład 1 – ASP.NETpublic 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);}

Gdzie jest problem? Pula wątków obsługujących żądania Dla uproszczenia – pula = 3 wątki; 3 procesory

HTMLDBWeb Servi

ceHTML HTML

CPU = 66%

Web Servi

ce

Gdzie jest problem? Pula wątków obsługujących żądania Dla uproszczenia – pula = 3 wątki; 3 procesory

HTML HTMLDBWeb Servi

ce

CPU = 33%

Web Servi

ceHTML

Gdzie jest problem? Pula wątków obsługujących żądania Dla uproszczenia – pula = 3 wątki; 3 procesory

HTML HTML DBWeb Servi

ce

CPU = 0%

Web Servi

ceHTML

!

Operacje obliczeniowe

Wątek

Operacje I/O (synchroniczne)

Operacja I/O

Wątek

Urządzenie

Gdyby… 1 cykl procesora = 1 sekunda:

Rejestr: 1s Pamięć: 5-10s Dysk: 3 miesiące Sieć: 30 lat

Przykład 2 - WPF

Przykład 2 - WPFvoid 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

Przykład 2 – WPF (aplikacja desktop) Tylko jeden wątek obsługuje UI W czasie wykonywania operacji aplikacja nie

odpowiada

Programowanie synchroniczneProblemy 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ę

Wzorce asynchroniczne

APM vs EAP vs TAP

Kod synchroniczny API:public interface IMyType{ int DoSomething(int a);}

Wywołanie:IMyType type = /*..*/;int result = type.DoSomething(10);

Asynchronous Programming ModelAPI

public interface IMyType{ IAsyncResult BeginDoSomething(int a, AsyncCallback callback, object state); int EndDoSomething(IAsyncResult asyncResult);}

Asynchronous Programming Model Użycie – wariant 1

IMyType type = /*..*/;IAsyncResult asyncRes = type.BeginDoSomething(10, null, null);//...int result = type.EndDoSomething(asyncRes);//...

Asynchronous Programming ModelUżycie – wariant 2class MyProgram{ private IMyType _type;

public void Begin() { _type.BeginDoSomething(10, OnDoSomethingFinished, null); }

private void OnDoSomethingFinished(IAsyncResult asyncRes) { int result = _type.EndDoSomething(asyncRes); //... }}

Asynchronous Programming ModelUżycie – wariant 2b

IMyType type = /*..*/;type.BeginDoSomething(10, asyncRes => { int result = type.EndDoSomething(asyncRes); //... }, null);

DemoAsynchronous Programming Model

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

Event-based Asynchronous ProgrammingAPIpublic 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);

Event-based Asynchronous ProgrammingUżycie

IMyType type = /*...*/;type.DoSomethingCompleted += (sender, args) => { int result = args.Result; //... };type.DoSomethingAsync(10);

DemoEvent-based Asynchronous Programming

APMZastosowanie 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

EAPZastosowanie FCL: 17 klas

System.ComponentModel.BackgroundWorker; System.Net.WebClient; System.Net.NetworkInformation.Ping; System.Windows.Forms.PictureBox; System.Net.Mail.SmtpClient; i inne…

APM czy EAP?

Gdzie jest problem?

Gdzie jest problem?

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

Idea TAP Niech deweloperzy piszą kod

prawie tak samo „Magią” niech zajmie się kompilator

Task-based Asynchronous ProgrammingAPI

public interface IMyType{ Task<int> DoSomethingTask(int a);}

Task-based Asynchronous ProgrammingAPI

public interface IMyType{ Task<int> DoSomethingTask(int a);}

Task-based Asynchronous ProgrammingUżycie

public async Task<bool> IsSomethingZeroAsync(int a){ IMyType type = /*...*/; var value = await type.DoSomethingAsync(a); return value == 0;}

Task-based Asynchronous ProgrammingUżycie

public async Task<bool> IsSomethingZeroAsync(int a){ IMyType type = /*...*/; var value = await type.DoSomethingAsync(a); return value == 0;}

Task-based Asynchronous ProgrammingUżycie

public async Task<bool> IsSomethingZeroAsync(int a){ IMyType type = /*...*/; var value = await type.DoSomethingAsync(a); return value == 0;}

Task-based Asynchronous ProgrammingUżycie

public async Task<bool> IsSomethingZeroAsync(int a){ IMyType type = /*...*/; var value = await type.DoSomethingAsync(a); return value == 0;}

DemoTask-based Asynchronous Programming

ASP.NET

Asynchroniczne ASP.NET MVC 3 i 4

DemoASP.NET MVC 3

Synchroniczny kontrolerASP.NET MVC 3public class HomeController : Controller{    public ActionResult AvatarDetails()    {        var client = new WebClient();        var data = client.DownloadData(new Uri("…"));        //...        return View();    }}

Asynchroniczny kontrolerASP.NET MVC 3public 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();    }}

Asynchroniczny kontrolerASP.NET MVC 3public 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();    }}

Asynchroniczny kontrolerASP.NET MVC 3public 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();    }}

Asynchroniczny kontrolerASP.NET MVC 3public 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();    }}

DemoASP.NET MVC 4 + async

Synchroniczny kontrolerASP.NET MVC 4public class HomeController : Controller{    public ActionResult AvatarDetails()    {        var client = new WebClient();        var data = client.DownloadData(new Uri("…"));        //...        return View();    }}

Asynchroniczny kontrolerASP.NET MVC 4public class HomeController : AsyncController{    public async Task<ActionResult> AvatarDetails()    {        var client = new WebClient();        var data = await client.DownloadDataTaskAsync(new Uri("…"));        //...        return View();    }}

Asynchroniczny kontrolerASP.NET MVC 4public class HomeController : AsyncController{    public async Task<ActionResult> AvatarDetails()    {        var client = new WebClient();        var data = await client.DownloadDataTaskAsync(new Uri("…"));        //...        return View();    }}

Asynchroniczny kontrolerASP.NET MVC 4public class HomeController : AsyncController{    public async Task<ActionResult> AvatarDetails()    {        var client = new WebClient();        var data = await client.DownloadDataTaskAsync(new Uri("…"));        //...        return View();    }}

„async” a testy jednostkowe

DemoSynchronous unit tests

DemoAsynchronous unit tests

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

Dziękuję za uwagę. Pytania?